From 8df29e239c14f74bca775742197e7e961a51a914 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Thu, 10 Oct 2024 13:49:22 +0200 Subject: [PATCH 01/33] Fix Linux build: Make the `nasm` feature a no-op (#7675) ### What * Circumvent https://github.com/rerun-io/rerun/issues/7671 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7675?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7675?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7675) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/store/re_video/Cargo.toml | 4 +++- crates/store/re_video/src/decode/av1.rs | 4 +++- crates/top/rerun-cli/Cargo.toml | 1 + crates/top/rerun/Cargo.toml | 1 + rerun_py/Cargo.toml | 1 + 5 files changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/store/re_video/Cargo.toml b/crates/store/re_video/Cargo.toml index 2dcad53f341a..afc07c39dcd3 100644 --- a/crates/store/re_video/Cargo.toml +++ b/crates/store/re_video/Cargo.toml @@ -31,7 +31,9 @@ av1 = ["dep:dav1d"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. -nasm = ["dav1d?/default"] # The default feature set of dav1d has asm enabled +# TODO(#7671): this feature flag currently does nothing +# nasm = ["dav1d?/default"] # The default feature set of dav1d has asm enabled +nasm = [] ## TODO(#7671): fix Linux build [dependencies] re_log.workspace = true diff --git a/crates/store/re_video/src/decode/av1.rs b/crates/store/re_video/src/decode/av1.rs index d4e69276a96e..dea52895e2e7 100644 --- a/crates/store/re_video/src/decode/av1.rs +++ b/crates/store/re_video/src/decode/av1.rs @@ -16,7 +16,9 @@ impl SyncDav1dDecoder { pub fn new() -> Result { re_tracing::profile_function!(); - if !cfg!(feature = "nasm") { + // TODO(#7671): enable this warning again when the `nasm` feature actually does something + #[allow(clippy::overly_complex_bool_expr)] + if false && !cfg!(feature = "nasm") { re_log::warn_once!( "NOTE: native AV1 video decoder is running extra slowly. \ Speed it up by compiling Rerun with the `nasm` feature enabled. \ diff --git a/crates/top/rerun-cli/Cargo.toml b/crates/top/rerun-cli/Cargo.toml index 405e07cb176d..1f0f0ef3c5b0 100644 --- a/crates/top/rerun-cli/Cargo.toml +++ b/crates/top/rerun-cli/Cargo.toml @@ -43,6 +43,7 @@ default = ["native_viewer", "web_viewer"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. +# TODO(#7671): this feature flag currently does nothing nasm = ["rerun/nasm"] ## Support spawning a native viewer. diff --git a/crates/top/rerun/Cargo.toml b/crates/top/rerun/Cargo.toml index 4a3c6adf6dd5..dfc1e8bccdde 100644 --- a/crates/top/rerun/Cargo.toml +++ b/crates/top/rerun/Cargo.toml @@ -73,6 +73,7 @@ log = ["dep:env_logger", "dep:log"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. +# TODO(#7671): this feature flag currently does nothing nasm = ["re_video/nasm"] ## Support spawning a native viewer. diff --git a/rerun_py/Cargo.toml b/rerun_py/Cargo.toml index 2b5994ab5de9..021a632313bf 100644 --- a/rerun_py/Cargo.toml +++ b/rerun_py/Cargo.toml @@ -30,6 +30,7 @@ extension-module = ["pyo3/extension-module"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. +# TODO(#7671): this feature flag currently does nothing nasm = ["re_video/nasm"] ## Support serving a web viewer over HTTP with `serve()`. From 370d99237323485a169a9f6f8533fc271e736a6c Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Thu, 10 Oct 2024 09:58:39 -0400 Subject: [PATCH 02/33] rerun_py.dataframe: add support for .filter_index_values (#7670) ### What - Add a new type helper for IndexValues (in general some variation of this will be useful for other APIs) - Added a dependency on `numpy` package for ArrayLike functionality - `numpy` has an old dep on ndarray. - This has already been fixed but not yet released: https://github.com/PyO3/rust-numpy/pull/439 - ChunkedArrays are sadly are more complicated (see the note in: https://docs.rs/arrow/latest/arrow/pyarrow/index.html) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7670?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7670?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7670) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- Cargo.lock | 47 ++++++-- Cargo.toml | 5 +- deny.toml | 1 + rerun_py/Cargo.toml | 1 + rerun_py/rerun_bindings/rerun_bindings.pyi | 12 +- rerun_py/rerun_bindings/types.py | 14 ++- rerun_py/src/dataframe.rs | 117 ++++++++++++++++++- rerun_py/tests/unit/test_dataframe.py | 128 ++++++++++++++++----- 8 files changed, 280 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6aff8cbde065..3949173b595c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3588,6 +3588,19 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c" +[[package]] +name = "ndarray" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "rawpointer", +] + [[package]] name = "ndarray" version = "0.16.1" @@ -3609,7 +3622,7 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f093b3db6fd194718dcdeea6bd8c829417deae904e3fcc7732dabcd4416d25d8" dependencies = [ - "ndarray", + "ndarray 0.16.1", "rand", "rand_distr", ] @@ -3846,6 +3859,21 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" +[[package]] +name = "numpy" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec170733ca37175f5d75a5bea5911d6ff45d2cd52849ce98b685394e4f2f37f4" +dependencies = [ + "libc", + "ndarray 0.15.6", + "num-complex", + "num-integer", + "num-traits", + "pyo3", + "rustc-hash", +] + [[package]] name = "objc" version = "0.2.7" @@ -5457,7 +5485,7 @@ dependencies = [ "document-features", "itertools 0.13.0", "libc", - "ndarray", + "ndarray 0.16.1", "ndarray-rand", "once_cell", "parking_lot", @@ -5647,7 +5675,7 @@ dependencies = [ "bytemuck", "egui", "half 2.3.1", - "ndarray", + "ndarray 0.16.1", "re_chunk_store", "re_data_ui", "re_log_types", @@ -5798,7 +5826,7 @@ dependencies = [ "linked-hash-map", "mime_guess2", "mint", - "ndarray", + "ndarray 0.16.1", "nohash-hasher", "once_cell", "ply-rs", @@ -6015,7 +6043,7 @@ dependencies = [ "indexmap 2.1.0", "itertools 0.13.0", "linked-hash-map", - "ndarray", + "ndarray 0.16.1", "nohash-hasher", "once_cell", "parking_lot", @@ -6289,6 +6317,7 @@ dependencies = [ "infer", "itertools 0.13.0", "mimalloc", + "numpy", "once_cell", "parking_lot", "pyo3", @@ -6461,7 +6490,7 @@ dependencies = [ "clap", "half 2.3.1", "image", - "ndarray", + "ndarray 0.16.1", "re_log", "rerun", ] @@ -6533,7 +6562,7 @@ version = "0.19.0-alpha.1+dev" dependencies = [ "anyhow", "clap", - "ndarray", + "ndarray 0.16.1", "re_log", "rerun", ] @@ -7016,7 +7045,7 @@ name = "snippets" version = "0.19.0-alpha.1+dev" dependencies = [ "itertools 0.13.0", - "ndarray", + "ndarray 0.16.1", "rand", "rand_distr", "re_build_tools", @@ -7188,7 +7217,7 @@ dependencies = [ "clap", "glam", "itertools 0.13.0", - "ndarray", + "ndarray 0.16.1", "ndarray-rand", "rand", "re_log", diff --git a/Cargo.toml b/Cargo.toml index 59262497c974..4865b52f5196 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -195,7 +195,7 @@ memory-stats = "1.1" # This version is not pinned to avoid creating version requirement conflicts, # but other packages pin it to exactly "=0.1.37" mimalloc = "0.1.37" -mime_guess2 = "2.0" # infer MIME type by file extension, and map mime to file extension +mime_guess2 = "2.0" # infer MIME type by file extension, and map mime to file extension mint = "0.5.9" re_mp4 = "0.1.0" natord = "1.0.9" @@ -206,6 +206,9 @@ nohash-hasher = "0.2" notify = { version = "6.1.1", features = ["macos_kqueue"] } num-derive = "0.4" num-traits = "0.2" +# TODO(#7676) This pulls in an older ndarray. Remove it from the skip list in `deny.toml` and +# close the issue when updating to 0.22. +numpy = "0.21" once_cell = "1.17" # No lazy_static - use `std::sync::OnceLock` or `once_cell` instead ordered-float = "4.2" parking_lot = "0.12" diff --git a/deny.toml b/deny.toml index d99c623c3e5d..2e1166e5f5e7 100644 --- a/deny.toml +++ b/deny.toml @@ -55,6 +55,7 @@ skip = [ { name = "hashbrown" }, # Old version used by polar-rs { name = "libloading" }, # Old version used by ash (vulkan binding), newer version used by khronos-egl { name = "memoffset" }, # Small crate + { name = "ndarray" }, # Needed by `numpy<0.22` in `rerun_py` { name = "prettyplease" }, # Old version being used by prost { name = "pulldown-cmark" }, # Build-dependency via `ply-rs` (!). TODO(emilk): use a better crate for .ply parsing { name = "raw-window-handle" }, # Pretty small crate; some crates still on old version diff --git a/rerun_py/Cargo.toml b/rerun_py/Cargo.toml index 021a632313bf..9c19c36591ba 100644 --- a/rerun_py/Cargo.toml +++ b/rerun_py/Cargo.toml @@ -67,6 +67,7 @@ infer.workspace = true # TODO(#5875): `mimalloc` starts leaking OS pages starting with `0.1.38`. # When the bug is fixed, change this back to `mimalloc = { workspace = true, …`. mimalloc = { version = "=0.1.37", features = ["local_dynamic_tls"] } +numpy.workspace = true once_cell.workspace = true parking_lot.workspace = true pyo3 = { workspace = true, features = ["abi3-py38"] } diff --git a/rerun_py/rerun_bindings/rerun_bindings.pyi b/rerun_py/rerun_bindings/rerun_bindings.pyi index ed9d606eae2f..72dcdb44801a 100644 --- a/rerun_py/rerun_bindings/rerun_bindings.pyi +++ b/rerun_py/rerun_bindings/rerun_bindings.pyi @@ -3,7 +3,7 @@ from typing import Optional, Sequence import pyarrow as pa -from .types import AnyColumn, ComponentLike, ViewContentsLike +from .types import AnyColumn, ComponentLike, IndexValuesLike, ViewContentsLike class IndexColumnDescriptor: """A column containing the index values for when the component data was updated.""" @@ -57,6 +57,16 @@ class RecordingView: """Filter the view to only include data between the given index time values.""" ... + def filter_index_values(self, values: IndexValuesLike) -> RecordingView: + """ + Filter the view to only include data at the given index values. + + This requires index values to be a precise match. Index values in Rerun are + represented as i64 sequence counts or nanoseconds. This API does not expose an interface + in floating point seconds, as the numerical conversion would risk false mismatches. + """ + ... + def select(self, *args: AnyColumn, columns: Optional[Sequence[AnyColumn]] = None) -> pa.RecordBatchReader: ... class Recording: diff --git a/rerun_py/rerun_bindings/types.py b/rerun_py/rerun_bindings/types.py index 7ad4207a8b63..87c219f21c9c 100644 --- a/rerun_py/rerun_bindings/types.py +++ b/rerun_py/rerun_bindings/types.py @@ -2,23 +2,27 @@ from typing import TYPE_CHECKING, Sequence, TypeAlias, Union +import numpy as np +import numpy.typing as npt +import pyarrow as pa + if TYPE_CHECKING: from rerun._baseclasses import ComponentMixin from .rerun_bindings import ( ComponentColumnDescriptor as ComponentColumnDescriptor, ComponentColumnSelector as ComponentColumnSelector, - TimeColumnDescriptor as TimeColumnDescriptor, - TimeColumnSelector as TimeColumnSelector, + IndexColumnSelector as IndexColumnDescriptor, + IndexColumnSelector as IndexColumnSelector, ) ComponentLike: TypeAlias = Union[str, type["ComponentMixin"]] AnyColumn: TypeAlias = Union[ - "TimeColumnDescriptor", "ComponentColumnDescriptor", - "TimeColumnSelector", "ComponentColumnSelector", + "IndexColumnDescriptor", + "IndexColumnSelector", ] AnyComponentColumn: TypeAlias = Union[ @@ -30,3 +34,5 @@ str, dict[str, Union[AnyColumn, Sequence[ComponentLike]]], ] + +IndexValuesLike: TypeAlias = Union[npt.NDArray[np.int_], pa.Int64Array] diff --git a/rerun_py/src/dataframe.rs b/rerun_py/src/dataframe.rs index dc7b027537d3..76698e5b7657 100644 --- a/rerun_py/src/dataframe.rs +++ b/rerun_py/src/dataframe.rs @@ -5,9 +5,10 @@ use std::collections::{BTreeMap, BTreeSet}; use arrow::{ - array::{RecordBatchIterator, RecordBatchReader}, + array::{make_array, Array, ArrayData, Int64Array, RecordBatchIterator, RecordBatchReader}, pyarrow::PyArrowType, }; +use numpy::PyArrayMethods as _; use pyo3::{ exceptions::{PyRuntimeError, PyTypeError, PyValueError}, prelude::*, @@ -195,6 +196,108 @@ impl AnyComponentColumn { } } +#[derive(FromPyObject)] +enum IndexValuesLike<'py> { + PyArrow(PyArrowType), + NumPy(numpy::PyArrayLike1<'py, i64>), + + // Catch all to support ChunkedArray and other types + #[pyo3(transparent)] + CatchAll(Bound<'py, PyAny>), +} + +impl<'py> IndexValuesLike<'py> { + fn to_index_values(&self) -> PyResult> { + match self { + Self::PyArrow(array) => { + let array = make_array(array.0.clone()); + + let int_array = array.as_any().downcast_ref::().ok_or_else(|| { + PyTypeError::new_err("pyarrow.Array for IndexValuesLike must be of type int64.") + })?; + + let values: BTreeSet = int_array + .iter() + .map(|v| { + v.map_or_else( + || re_chunk_store::TimeInt::STATIC, + // The use of temporal here should be fine even if the data is + // not actually temporal. The important thing is we are converting + // from an i64 input + re_chunk_store::TimeInt::new_temporal, + ) + }) + .collect(); + + if values.len() != int_array.len() { + return Err(PyValueError::new_err("Index values must be unique.")); + } + + Ok(values) + } + Self::NumPy(array) => { + let values: BTreeSet = array + .readonly() + .as_array() + .iter() + // The use of temporal here should be fine even if the data is + // not actually temporal. The important thing is we are converting + // from an i64 input + .map(|v| re_chunk_store::TimeInt::new_temporal(*v)) + .collect(); + + if values.len() != array.len()? { + return Err(PyValueError::new_err("Index values must be unique.")); + } + + Ok(values) + } + Self::CatchAll(any) => { + // If any has the `.chunks` attribute, we can try to try each chunk as pyarrow array + if let Ok(chunks) = any.getattr("chunks") { + let mut values = BTreeSet::new(); + for chunk in chunks.iter()? { + let chunk = chunk?.extract::>()?; + let array = make_array(chunk.0.clone()); + + let int_array = + array.as_any().downcast_ref::().ok_or_else(|| { + PyTypeError::new_err( + "pyarrow.Array for IndexValuesLike must be of type int64.", + ) + })?; + + values.extend( + int_array + .iter() + .map(|v| { + v.map_or_else( + || re_chunk_store::TimeInt::STATIC, + // The use of temporal here should be fine even if the data is + // not actually temporal. The important thing is we are converting + // from an i64 input + re_chunk_store::TimeInt::new_temporal, + ) + }) + .collect::>(), + ); + } + + if values.len() != any.len()? { + return Err(PyValueError::new_err("Index values must be unique.")); + } + + Ok(values) + } else { + Err(PyTypeError::new_err( + "IndexValuesLike must be a pyarrow.Array, pyarrow.ChunkedArray, or numpy.ndarray", + )) + } + } + } + } +} + struct ComponentLike(re_sdk::ComponentName); impl FromPyObject<'_> for ComponentLike { @@ -438,6 +541,18 @@ impl PyRecordingView { query_expression, }) } + + fn filter_index_values(&self, values: IndexValuesLike<'_>) -> PyResult { + let values = values.to_index_values()?; + + let mut query_expression = self.query_expression.clone(); + query_expression.filtered_index_values = Some(values); + + Ok(Self { + recording: self.recording.clone(), + query_expression, + }) + } } impl PyRecording { diff --git a/rerun_py/tests/unit/test_dataframe.py b/rerun_py/tests/unit/test_dataframe.py index 93183f42f8d1..06b967bdb937 100644 --- a/rerun_py/tests/unit/test_dataframe.py +++ b/rerun_py/tests/unit/test_dataframe.py @@ -5,6 +5,7 @@ import uuid import pyarrow as pa +import pytest import rerun as rr APP_ID = "rerun_example_test_recording" @@ -59,6 +60,32 @@ def setup_method(self) -> None: self.recording = rr.dataframe.load_recording(rrd) + self.expected_index0 = pa.array( + [1], + type=pa.int64(), + ) + + self.expected_index1 = pa.array( + [7], + type=pa.int64(), + ) + + self.expected_pos0 = pa.array( + [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], + ], + type=rr.components.Position3D.arrow_type(), + ) + + self.expected_pos1 = pa.array( + [ + [10, 11, 12], + ], + type=rr.components.Position3D.arrow_type(), + ) + def test_recording_info(self) -> None: assert self.recording.application_id() == APP_ID assert self.recording.recording_id() == str(RECORDING_ID) @@ -75,48 +102,91 @@ def test_full_view(self) -> None: def test_select_columns(self) -> None: view = self.recording.view(index="my_index", contents="points") - log_time = rr.dataframe.IndexColumnSelector("my_index") + index_col = rr.dataframe.IndexColumnSelector("my_index") pos = rr.dataframe.ComponentColumnSelector("points", rr.components.Position3D) - batches = view.select(log_time, pos) + batches = view.select(index_col, pos) table = pa.Table.from_batches(batches, batches.schema) # points assert table.num_columns == 2 assert table.num_rows == 2 - expected_index0 = pa.array( - [1], - type=pa.int64(), - ) + assert table.column("my_index")[0].equals(self.expected_index0[0]) + assert table.column("my_index")[1].equals(self.expected_index1[0]) + assert table.column("/points:Position3D")[0].values.equals(self.expected_pos0) + assert table.column("/points:Position3D")[1].values.equals(self.expected_pos1) - expected_index1 = pa.array( - [7], - type=pa.int64(), - ) + def test_index_values(self) -> None: + view = self.recording.view(index="my_index", contents="points") + view = view.filter_index_values([1, 7, 9]) - expected_pos0 = pa.array( - [ - [1, 2, 3], - [4, 5, 6], - [7, 8, 9], - ], - type=rr.components.Position3D.arrow_type(), - ) + batches = view.select() + table = pa.Table.from_batches(batches, batches.schema) - expected_pos1 = pa.array( - [ - [10, 11, 12], - ], - type=rr.components.Position3D.arrow_type(), - ) + # my_index, log_time, log_tick, points, colors + assert table.num_columns == 5 + assert table.num_rows == 2 + + assert table.column("my_index")[0].equals(self.expected_index0[0]) + assert table.column("my_index")[1].equals(self.expected_index1[0]) + + # This is a chunked array + new_selection_chunked = table.column("my_index").take([1]) + + # This is a single array + new_selection = new_selection_chunked.combine_chunks() + + view2 = view.filter_index_values(new_selection_chunked) + batches = view2.select() + table2 = pa.Table.from_batches(batches, batches.schema) + + # my_index, log_time, log_tick, points, colors + assert table2.num_columns == 5 + assert table2.num_rows == 1 + + assert table2.column("my_index")[0].equals(self.expected_index1[0]) + + view3 = view.filter_index_values(new_selection) + batches = view3.select() + table3 = pa.Table.from_batches(batches, batches.schema) + + assert table3 == table2 + + # Manually create a pyarrow array with no matches + view4 = view.filter_index_values(pa.array([8], type=pa.int64())) + batches = view4.select() + table4 = pa.Table.from_batches(batches, batches.schema) + + assert table4.num_rows == 0 + + # Manually create a chunked array with 1 match + manual_chunked_selection = pa.chunked_array([ + pa.array([2], type=pa.int64()), + pa.array([3, 7, 8], type=pa.int64()), + pa.array([], type=pa.int64()), + pa.array([9, 10, 11], type=pa.int64()), + ]) + + # Confirm len is num elements, not num chunks + assert len(manual_chunked_selection) == 7 + assert len(manual_chunked_selection.chunks) == 4 + + view5 = view.filter_index_values(manual_chunked_selection) + batches = view5.select() + table5 = pa.Table.from_batches(batches, batches.schema) + + assert table5.num_rows == 1 + + # Exceptions + with pytest.raises(ValueError): + view.filter_index_values(pa.array([8, 8], type=pa.int64())) - print(table.schema) + with pytest.raises(TypeError): + view.filter_index_values("1") - assert table.column("my_index")[0].equals(expected_index0[0]) - assert table.column("my_index")[1].equals(expected_index1[0]) - assert table.column("/points:Position3D")[0].values.equals(expected_pos0) - assert table.column("/points:Position3D")[1].values.equals(expected_pos1) + with pytest.raises(TypeError): + view.filter_index_values(pa.array([1.0, 2.0], type=pa.float64())) def test_view_syntax(self) -> None: good_content_expressions = [ From 06cfa9eb1c8facb435bf7de6991aa0513781e8a6 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Thu, 10 Oct 2024 17:00:21 +0200 Subject: [PATCH 03/33] New planar pixel formats: `Y_U_V24`/`Y_U_V16`/`Y_U_V12` - `_LimitedRange`/`FullRange` (#7666) ### What Adds a whole bunch of new pixel formats with limited & full range YUV variants. All of these are needed by our AV1 decoder (branch is a misnomer though, this is coming in another pr!) ---- Naming & categorizing these formats is quite the struggle just as expected: If limited to YUV variants, the overall picutre becomes sharper (ironic, eh) and it's possible to specify the combinatorics in a deceptively simple pattern: * planarity & downsample ratio * limited/full value range * bit depth (we only do 8 bit right now) * color primaries That's what is happening in `re_renderer`'s YUV converter now and is very useful for writing the conversions themselves! However (!!!), in the wild names make these properties often convoluted with each other, making the categorization a lot harder. E.g. NV12 is almost always (afaik just _almost_) implying `LimitedRange` YUV (which is generally a common default unless you're dealing with jpeg derived data [...]). This, and the fact that we already set out with `PixelFormat` for a flat list of names, strongly compelled me to continue the current naming scheme (and Ocean's numbering as far as possible) in the user facing API. Worth revisiting in the future. The primary motivation to expose these formats right away was to be able to easily test these variants. However, I refrained from throwing color primaries into the mix here because I think they should in fact be separately defined, causing a bigger expansion of the APIs. The docs are intentionally kept vague on color space for the moment (trying hard to not further get entangled here). As a result, our internal processing is now fairly explicit on the matter, but the input interpretation is rather vague. image (screenshot of the release checklist which is part of this pr (moved from a previous test). I manually tested the color inspection feature against a reference color picker - slight rounding errors occasionally, but they are hard to avoid since GPU/CPU don't always do the exact same thing :/) https://rerun.io/viewer/pr/7666?url=https%3A%2F%2Fstatic.rerun.io%2Frrd%2F0.19.0%2Fchroma_4688549ca3c20018fa2fb658b56482b955817b6a.rrd ### Checklist * [ ] chrome/firefox windows * [x] chrome/firefox/safari mac * [ ] chrome/firefox linux * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7666?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7666?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7666) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .gitignore | 1 + .../re_types_builder/src/codegen/rust/api.rs | 5 + .../rerun/datatypes/pixel_format.fbs | 77 +++++- .../blueprint/components/background_kind.rs | 1 + .../src/blueprint/components/corner2d.rs | 1 + .../src/blueprint/components/panel_state.rs | 1 + .../src/blueprint/components/view_fit.rs | 1 + .../src/components/aggregation_policy.rs | 1 + .../store/re_types/src/components/colormap.rs | 1 + .../re_types/src/components/fill_mode.rs | 1 + .../src/components/magnification_filter.rs | 1 + .../re_types/src/components/marker_shape.rs | 1 + .../src/components/transform_relation.rs | 1 + .../src/datatypes/channel_datatype.rs | 1 + .../re_types/src/datatypes/color_model.rs | 1 + .../re_types/src/datatypes/pixel_format.rs | 139 ++++++++++- .../src/datatypes/pixel_format_ext.rs | 157 +++++++++++- crates/store/re_types/src/image.rs | 92 +++++-- .../src/testing/datatypes/enum_test.rs | 1 + .../src/testing/datatypes/valued_enum.rs | 1 + .../blueprint/components/container_kind.rs | 1 + .../shader/conversions/yuv_converter.wgsl | 125 ++++++++-- .../image_data_to_texture.rs | 17 +- .../re_renderer/src/resource_managers/mod.rs | 2 +- .../src/resource_managers/yuv_converter.rs | 194 +++++++++++++-- .../src/gpu_bridge/image_to_gpu.rs | 87 +++++-- .../re_viewer_context/src/image_info.rs | 8 +- .../src/tensor/image_stats.rs | 9 +- .../reference/types/datatypes/pixel_format.md | 8 + .../src/rerun/datatypes/pixel_format.hpp | 73 +++++- rerun_cpp/src/rerun/image_utils.hpp | 21 +- .../rerun_sdk/rerun/datatypes/pixel_format.py | 116 ++++++++- tests/python/chroma_downsample_image/main.py | 85 ------- .../chroma_downsample_image/requirements.txt | 3 - .../check_chroma_subsampling.py | 235 ++++++++++++++++++ 35 files changed, 1269 insertions(+), 200 deletions(-) delete mode 100755 tests/python/chroma_downsample_image/main.py delete mode 100644 tests/python/chroma_downsample_image/requirements.txt create mode 100644 tests/python/release_checklist/check_chroma_subsampling.py diff --git a/.gitignore b/.gitignore index 0a4c662a860e..44cbc46e9872 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ _deps # Python build artifacts: __pycache__ *.pyc +*.pyd *.so **/.pytest_cache diff --git a/crates/build/re_types_builder/src/codegen/rust/api.rs b/crates/build/re_types_builder/src/codegen/rust/api.rs index 5545f8855fcd..4f31be5ed752 100644 --- a/crates/build/re_types_builder/src/codegen/rust/api.rs +++ b/crates/build/re_types_builder/src/codegen/rust/api.rs @@ -161,6 +161,11 @@ fn generate_object_file( code.push_str("#![allow(deprecated)]\n"); } + if obj.is_enum() { + // Needed for PixelFormat. Should we limit this via attribute to just that? + code.push_str("#![allow(non_camel_case_types)]\n"); + } + code.push_str("\n\n"); code.push_str("use ::re_types_core::external::arrow2;\n"); diff --git a/crates/store/re_types/definitions/rerun/datatypes/pixel_format.fbs b/crates/store/re_types/definitions/rerun/datatypes/pixel_format.fbs index 298ba8736268..d0073e1ad2a3 100644 --- a/crates/store/re_types/definitions/rerun/datatypes/pixel_format.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes/pixel_format.fbs @@ -1,5 +1,9 @@ namespace rerun.datatypes; +// TODO(andreas): Clarify relationship to color primaries. Right now there's some hardcoded differences between formats. +// See `image_to_gpu.rs` +// Suggestion: guides heuristic but doesn't specify it unless noted. + /// Specifieds a particular format of an [archetypes.Image]. /// /// Most images can be described by a [datatypes.ColorModel] and a [datatypes.ChannelDatatype], @@ -24,13 +28,82 @@ enum PixelFormat: ubyte { // this organization and subsequently reduce the chance we may find ourselves wanting to // change the values in the future. - /// `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled format with 12 bits per pixel and 8 bits per channel. + /// `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes. + Y_U_V24_LimitedRange = 39, + + /// `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes. + Y_U_V24_FullRange = 40, + + /// `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the horizontal resolution of the Y plane. + Y_U_V16_LimitedRange = 49, // Ocean doesn't have a short codes for this + + /// `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the horizontal resolution of the Y plane. + Y_U_V16_FullRange = 50, // Ocean doesn't have a short codes for this + + /// `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the resolution of the Y plane. + Y_U_V12_LimitedRange = 20, + + /// `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the resolution of the Y plane. + Y_U_V12_FullRange = 44, + + /// Monochrome Y plane only, essentially a YUV 4:0:0 planar format. + /// + /// Also known as just "gray". + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235]. + /// If not for this range limitation/remapping, this is almost identical to 8bit luminace/grayscale (see [datatypes.ColorModel]). + Y8_LimitedRange = 41, + + /// Monochrome Y plane only, essentially a YUV 4:0:0 planar format. + /// + /// Also known as just "gray". This is virtually identical to a 8bit luminance/grayscale (see [datatypes.ColorModel]). + /// + /// This uses entire range YUV, i.e. Y is expected to be within [0, 255]. + /// (as opposed to "limited range" YUV as used e.g. in NV12). + Y8_FullRange = 30, + + /// `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled form at with 12 bits per pixel and 8 bits per channel. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. /// /// First comes entire image in Y in one plane, /// followed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc. NV12 = 26 (default), // _something_ has to be the default 🤷‍♀️ - /// `YUY2` (aka `YUYV` or `YUYV16`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. + /// `YUY2` (aka `YUYV`, `YUYV16` or `NV21`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. /// /// The order of the channels is Y0, U0, Y1, V0, all in the same plane. YUY2 = 27, diff --git a/crates/store/re_types/src/blueprint/components/background_kind.rs b/crates/store/re_types/src/blueprint/components/background_kind.rs index 90f72396843d..d924523cc4f2 100644 --- a/crates/store/re_types/src/blueprint/components/background_kind.rs +++ b/crates/store/re_types/src/blueprint/components/background_kind.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/blueprint/components/corner2d.rs b/crates/store/re_types/src/blueprint/components/corner2d.rs index 794dbec2b288..f5d00addf4a2 100644 --- a/crates/store/re_types/src/blueprint/components/corner2d.rs +++ b/crates/store/re_types/src/blueprint/components/corner2d.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/blueprint/components/panel_state.rs b/crates/store/re_types/src/blueprint/components/panel_state.rs index b8eaee2edd87..a03e05b80050 100644 --- a/crates/store/re_types/src/blueprint/components/panel_state.rs +++ b/crates/store/re_types/src/blueprint/components/panel_state.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/blueprint/components/view_fit.rs b/crates/store/re_types/src/blueprint/components/view_fit.rs index eef956af788b..e99228f743d7 100644 --- a/crates/store/re_types/src/blueprint/components/view_fit.rs +++ b/crates/store/re_types/src/blueprint/components/view_fit.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/components/aggregation_policy.rs b/crates/store/re_types/src/components/aggregation_policy.rs index 524bee85abb6..c8b696f5a2d2 100644 --- a/crates/store/re_types/src/components/aggregation_policy.rs +++ b/crates/store/re_types/src/components/aggregation_policy.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/components/colormap.rs b/crates/store/re_types/src/components/colormap.rs index 313ae8a074d1..3110a4077440 100644 --- a/crates/store/re_types/src/components/colormap.rs +++ b/crates/store/re_types/src/components/colormap.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/components/fill_mode.rs b/crates/store/re_types/src/components/fill_mode.rs index ad79a15162ca..d434fd8d1a4a 100644 --- a/crates/store/re_types/src/components/fill_mode.rs +++ b/crates/store/re_types/src/components/fill_mode.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/components/magnification_filter.rs b/crates/store/re_types/src/components/magnification_filter.rs index d704bd593946..be0b6392be3d 100644 --- a/crates/store/re_types/src/components/magnification_filter.rs +++ b/crates/store/re_types/src/components/magnification_filter.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/components/marker_shape.rs b/crates/store/re_types/src/components/marker_shape.rs index b2da33d1dcd7..78da7ffeb1f9 100644 --- a/crates/store/re_types/src/components/marker_shape.rs +++ b/crates/store/re_types/src/components/marker_shape.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/components/transform_relation.rs b/crates/store/re_types/src/components/transform_relation.rs index d3543234659d..06137a33b181 100644 --- a/crates/store/re_types/src/components/transform_relation.rs +++ b/crates/store/re_types/src/components/transform_relation.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/datatypes/channel_datatype.rs b/crates/store/re_types/src/datatypes/channel_datatype.rs index d5c0d6222740..e58e4d970e7d 100644 --- a/crates/store/re_types/src/datatypes/channel_datatype.rs +++ b/crates/store/re_types/src/datatypes/channel_datatype.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/datatypes/color_model.rs b/crates/store/re_types/src/datatypes/color_model.rs index 0dfe0ae4224c..48a677a4bbe7 100644 --- a/crates/store/re_types/src/datatypes/color_model.rs +++ b/crates/store/re_types/src/datatypes/color_model.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/datatypes/pixel_format.rs b/crates/store/re_types/src/datatypes/pixel_format.rs index 45d808a40f0b..348b292cd930 100644 --- a/crates/store/re_types/src/datatypes/pixel_format.rs +++ b/crates/store/re_types/src/datatypes/pixel_format.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; @@ -32,7 +33,18 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Default)] #[repr(u8)] pub enum PixelFormat { - /// `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled format with 12 bits per pixel and 8 bits per channel. + /// `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the resolution of the Y plane. + #[allow(clippy::upper_case_acronyms)] + Y_U_V12_LimitedRange = 20, + + /// `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled form at with 12 bits per pixel and 8 bits per channel. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. /// /// First comes entire image in Y in one plane, /// followed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc. @@ -40,27 +52,128 @@ pub enum PixelFormat { #[allow(clippy::upper_case_acronyms)] NV12 = 26, - /// `YUY2` (aka `YUYV` or `YUYV16`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. + /// `YUY2` (aka `YUYV`, `YUYV16` or `NV21`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. /// /// The order of the channels is Y0, U0, Y1, V0, all in the same plane. #[allow(clippy::upper_case_acronyms)] YUY2 = 27, + + /// Monochrome Y plane only, essentially a YUV 4:0:0 planar format. + /// + /// Also known as just "gray". This is virtually identical to a 8bit luminance/grayscale (see [`datatypes::ColorModel`][crate::datatypes::ColorModel]). + /// + /// This uses entire range YUV, i.e. Y is expected to be within [0, 255]. + /// (as opposed to "limited range" YUV as used e.g. in NV12). + #[allow(clippy::upper_case_acronyms)] + Y8_FullRange = 30, + + /// `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes. + #[allow(clippy::upper_case_acronyms)] + Y_U_V24_LimitedRange = 39, + + /// `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes. + #[allow(clippy::upper_case_acronyms)] + Y_U_V24_FullRange = 40, + + /// Monochrome Y plane only, essentially a YUV 4:0:0 planar format. + /// + /// Also known as just "gray". + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235]. + /// If not for this range limitation/remapping, this is almost identical to 8bit luminace/grayscale (see [`datatypes::ColorModel`][crate::datatypes::ColorModel]). + #[allow(clippy::upper_case_acronyms)] + Y8_LimitedRange = 41, + + /// `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the resolution of the Y plane. + #[allow(clippy::upper_case_acronyms)] + Y_U_V12_FullRange = 44, + + /// `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the horizontal resolution of the Y plane. + #[allow(clippy::upper_case_acronyms)] + Y_U_V16_LimitedRange = 49, + + /// `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the horizontal resolution of the Y plane. + #[allow(clippy::upper_case_acronyms)] + Y_U_V16_FullRange = 50, } impl ::re_types_core::reflection::Enum for PixelFormat { #[inline] fn variants() -> &'static [Self] { - &[Self::NV12, Self::YUY2] + &[ + Self::Y_U_V12_LimitedRange, + Self::NV12, + Self::YUY2, + Self::Y8_FullRange, + Self::Y_U_V24_LimitedRange, + Self::Y_U_V24_FullRange, + Self::Y8_LimitedRange, + Self::Y_U_V12_FullRange, + Self::Y_U_V16_LimitedRange, + Self::Y_U_V16_FullRange, + ] } #[inline] fn docstring_md(self) -> &'static str { match self { + Self::Y_U_V12_LimitedRange => { + "`Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`.\n\nThis uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240].\n\nFirst comes entire image in Y in one plane, followed by the U and V planes, which each only have half\nthe resolution of the Y plane." + } Self::NV12 => { - "`NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled format with 12 bits per pixel and 8 bits per channel.\n\nFirst comes entire image in Y in one plane,\nfollowed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc." + "`NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled form at with 12 bits per pixel and 8 bits per channel.\n\nThis uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240].\n\nFirst comes entire image in Y in one plane,\nfollowed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc." } Self::YUY2 => { - "`YUY2` (aka `YUYV` or `YUYV16`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel.\n\nThe order of the channels is Y0, U0, Y1, V0, all in the same plane." + "`YUY2` (aka `YUYV`, `YUYV16` or `NV21`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel.\n\nThis uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240].\n\nThe order of the channels is Y0, U0, Y1, V0, all in the same plane." + } + Self::Y8_FullRange => { + "Monochrome Y plane only, essentially a YUV 4:0:0 planar format.\n\nAlso known as just \"gray\". This is virtually identical to a 8bit luminance/grayscale (see [`datatypes::ColorModel`][crate::datatypes::ColorModel]).\n\nThis uses entire range YUV, i.e. Y is expected to be within [0, 255].\n(as opposed to \"limited range\" YUV as used e.g. in NV12)." + } + Self::Y_U_V24_LimitedRange => { + "`Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`.\n\nThis uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240].\n\nFirst comes entire image in Y in one plane, followed by the U and V planes." + } + Self::Y_U_V24_FullRange => { + "`Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`.\n\nThis uses full range YUV with all components ranging from 0 to 255\n(as opposed to \"limited range\" YUV as used e.g. in NV12).\n\nFirst comes entire image in Y in one plane, followed by the U and V planes." + } + Self::Y8_LimitedRange => { + "Monochrome Y plane only, essentially a YUV 4:0:0 planar format.\n\nAlso known as just \"gray\".\n\nThis uses limited range YUV, i.e. Y is expected to be within [16, 235].\nIf not for this range limitation/remapping, this is almost identical to 8bit luminace/grayscale (see [`datatypes::ColorModel`][crate::datatypes::ColorModel])." + } + Self::Y_U_V12_FullRange => { + "`Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`.\n\nThis uses full range YUV with all components ranging from 0 to 255\n(as opposed to \"limited range\" YUV as used e.g. in NV12).\n\nFirst comes entire image in Y in one plane, followed by the U and V planes, which each only have half\nthe resolution of the Y plane." + } + Self::Y_U_V16_LimitedRange => { + "`Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`.\n\nThis uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240].\n\nFirst comes entire image in Y in one plane, followed by the U and V planes, which each only have half\nthe horizontal resolution of the Y plane." + } + Self::Y_U_V16_FullRange => { + "`Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`.\n\nThis uses full range YUV with all components ranging from 0 to 255\n(as opposed to \"limited range\" YUV as used e.g. in NV12).\n\nFirst comes entire image in Y in one plane, followed by the U and V planes, which each only have half\nthe horizontal resolution of the Y plane." } } } @@ -81,8 +194,16 @@ impl ::re_types_core::SizeBytes for PixelFormat { impl std::fmt::Display for PixelFormat { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + Self::Y_U_V12_LimitedRange => write!(f, "Y_U_V12_LimitedRange"), Self::NV12 => write!(f, "NV12"), Self::YUY2 => write!(f, "YUY2"), + Self::Y8_FullRange => write!(f, "Y8_FullRange"), + Self::Y_U_V24_LimitedRange => write!(f, "Y_U_V24_LimitedRange"), + Self::Y_U_V24_FullRange => write!(f, "Y_U_V24_FullRange"), + Self::Y8_LimitedRange => write!(f, "Y8_LimitedRange"), + Self::Y_U_V12_FullRange => write!(f, "Y_U_V12_FullRange"), + Self::Y_U_V16_LimitedRange => write!(f, "Y_U_V16_LimitedRange"), + Self::Y_U_V16_FullRange => write!(f, "Y_U_V16_FullRange"), } } } @@ -157,8 +278,16 @@ impl ::re_types_core::Loggable for PixelFormat { .into_iter() .map(|opt| opt.copied()) .map(|typ| match typ { + Some(20) => Ok(Some(Self::Y_U_V12_LimitedRange)), Some(26) => Ok(Some(Self::NV12)), Some(27) => Ok(Some(Self::YUY2)), + Some(30) => Ok(Some(Self::Y8_FullRange)), + Some(39) => Ok(Some(Self::Y_U_V24_LimitedRange)), + Some(40) => Ok(Some(Self::Y_U_V24_FullRange)), + Some(41) => Ok(Some(Self::Y8_LimitedRange)), + Some(44) => Ok(Some(Self::Y_U_V12_FullRange)), + Some(49) => Ok(Some(Self::Y_U_V16_LimitedRange)), + Some(50) => Ok(Some(Self::Y_U_V16_FullRange)), None => Ok(None), Some(invalid) => Err(DeserializationError::missing_union_arm( Self::arrow_datatype(), diff --git a/crates/store/re_types/src/datatypes/pixel_format_ext.rs b/crates/store/re_types/src/datatypes/pixel_format_ext.rs index 23191ec886f1..55b12e01888b 100644 --- a/crates/store/re_types/src/datatypes/pixel_format_ext.rs +++ b/crates/store/re_types/src/datatypes/pixel_format_ext.rs @@ -1,4 +1,4 @@ -use crate::image::rgb_from_yuv; +use crate::image::{rgb_from_yuv, ColorPrimaries}; use super::{ChannelDatatype, ColorModel, PixelFormat}; @@ -7,7 +7,16 @@ impl PixelFormat { #[inline] pub fn has_alpha(&self) -> bool { match self { - Self::NV12 | Self::YUY2 => false, + Self::Y_U_V12_FullRange + | Self::Y_U_V16_FullRange + | Self::Y_U_V24_FullRange + | Self::Y8_FullRange + | Self::Y_U_V12_LimitedRange + | Self::Y_U_V16_LimitedRange + | Self::Y_U_V24_LimitedRange + | Self::Y8_LimitedRange + | Self::NV12 + | Self::YUY2 => false, } } @@ -15,7 +24,16 @@ impl PixelFormat { /// Is this pixel format floating point? pub fn is_float(&self) -> bool { match self { - Self::NV12 | Self::YUY2 => false, + Self::Y_U_V12_FullRange + | Self::Y_U_V16_FullRange + | Self::Y_U_V24_FullRange + | Self::Y8_FullRange + | Self::Y_U_V12_LimitedRange + | Self::Y_U_V16_LimitedRange + | Self::Y_U_V24_LimitedRange + | Self::Y8_LimitedRange + | Self::NV12 + | Self::YUY2 => false, } } @@ -24,16 +42,47 @@ impl PixelFormat { pub fn num_bytes(&self, [w, h]: [u32; 2]) -> usize { let num_pixels = w as usize * h as usize; match self { - Self::NV12 => 12 * num_pixels / 8, - Self::YUY2 => 16 * num_pixels / 8, + // 444 formats. + Self::Y_U_V24_FullRange | Self::Y_U_V24_LimitedRange => num_pixels * 4, + + // 422 formats. + Self::Y_U_V16_FullRange | Self::Y_U_V16_LimitedRange | Self::NV12 => { + 16 * num_pixels / 8 + } + + // 420 formats. + Self::Y_U_V12_FullRange | Self::Y_U_V12_LimitedRange | Self::YUY2 => { + 12 * num_pixels / 8 + } + + // Monochrome formats. + Self::Y8_LimitedRange | Self::Y8_FullRange => num_pixels, } } /// The color model derived from this pixel format. #[inline] pub fn color_model(&self) -> ColorModel { + #[allow(clippy::match_same_arms)] match self { - Self::NV12 | Self::YUY2 => ColorModel::RGB, + Self::Y_U_V12_FullRange + | Self::Y_U_V16_FullRange + | Self::Y_U_V24_FullRange + | Self::Y_U_V12_LimitedRange + | Self::Y_U_V16_LimitedRange + | Self::Y_U_V24_LimitedRange + | Self::NV12 + | Self::YUY2 => ColorModel::RGB, + + // TODO(andreas): This shouldn't be ColorModel::RGB, but our YUV converter can't do anything else right now: + // The converter doesn't *have* to always output RGB, but having it sometimes output R(8) specifically for the + // YUV converter requires me to do more bookkeeping (needs a new renderpipeline and I expect other ripples). + // + // As of writing, having this color_model "incorrectly" be RGB mostly affects hovering logic which will continue to show RGB rather than L. + // + // Note that this does not affect the memory Y8 needs. It just implies that we use more GPU memory than we should. + // However, we typically (see image cache) hold the converted GPU textures only as long as we actually draw with them. + Self::Y8_LimitedRange | Self::Y8_FullRange => ColorModel::RGB, } } @@ -41,7 +90,16 @@ impl PixelFormat { /// The datatype that this decodes into. pub fn datatype(&self) -> ChannelDatatype { match self { - Self::NV12 | Self::YUY2 => ChannelDatatype::U8, + Self::Y_U_V12_FullRange + | Self::Y_U_V16_FullRange + | Self::Y_U_V24_FullRange + | Self::Y8_FullRange + | Self::Y_U_V12_LimitedRange + | Self::Y_U_V16_LimitedRange + | Self::Y_U_V24_LimitedRange + | Self::Y8_LimitedRange + | Self::NV12 + | Self::YUY2 => ChannelDatatype::U8, } } @@ -51,6 +109,45 @@ impl PixelFormat { #[inline] pub fn decode_yuv_at(&self, buf: &[u8], [w, h]: [u32; 2], [x, y]: [u32; 2]) -> Option<[u8; 3]> { match self { + Self::Y_U_V24_FullRange | Self::Y_U_V24_LimitedRange => { + let plane_size = (w * h) as usize; + let plane_coord = (y * w + x) as usize; + + let luma = *buf.get(plane_coord)?; + let u = *buf.get(plane_coord + plane_size)?; + let v = *buf.get(plane_coord + plane_size * 2)?; + Some([luma, u, v]) + } + + Self::Y_U_V16_FullRange | Self::Y_U_V16_LimitedRange => { + let y_plane_size = (w * h) as usize; + let uv_plane_size = y_plane_size / 2; // Half horizontal resolution. + let y_plane_coord = (y * w + x) as usize; + let uv_plane_coord = y_plane_coord / 2; // == (y * (w / 2) + x / 2) + + let luma = *buf.get(y_plane_coord)?; + let u = *buf.get(uv_plane_coord + y_plane_size)?; + let v = *buf.get(uv_plane_coord + y_plane_size + uv_plane_size)?; + Some([luma, u, v]) + } + + Self::Y_U_V12_FullRange | Self::Y_U_V12_LimitedRange => { + let y_plane_size = (w * h) as usize; + let uv_plane_size = y_plane_size / 4; // Half horizontal & vertical resolution. + let y_plane_coord = (y * w + x) as usize; + let uv_plane_coord = (y * w / 4 + x / 2) as usize; // == ((y / 2) * (w / 2) + x / 2) + + let luma = *buf.get(y_plane_coord)?; + let u = *buf.get(uv_plane_coord + y_plane_size)?; + let v = *buf.get(uv_plane_coord + y_plane_size + uv_plane_size)?; + Some([luma, u, v]) + } + + Self::Y8_FullRange | Self::Y8_LimitedRange => { + let luma = *buf.get((y * w + x) as usize)?; + Some([luma, 128, 128]) + } + Self::NV12 => { let uv_offset = w * h; let luma = *buf.get((y * w + x) as usize)?; @@ -70,12 +167,56 @@ impl PixelFormat { } } + /// Returns true if the format is a YUV format using + /// limited range YUV. + /// + /// I.e. for 8bit data, Y is valid in [16, 235] and U/V [16, 240], rather than 0-255. + pub fn is_limited_yuv_range(&self) -> bool { + match self { + Self::Y_U_V24_LimitedRange + | Self::Y_U_V16_LimitedRange + | Self::Y_U_V12_LimitedRange + | Self::Y8_LimitedRange + | Self::NV12 + | Self::YUY2 => true, + + Self::Y_U_V24_FullRange + | Self::Y_U_V12_FullRange + | Self::Y_U_V16_FullRange + | Self::Y8_FullRange => false, + } + } + + /// Color primaries used by this format. + // TODO(andreas): Expose this in the API separately and document it better. + pub fn color_primaries(&self) -> ColorPrimaries { + match self { + Self::Y_U_V24_LimitedRange + | Self::Y_U_V24_FullRange + | Self::Y_U_V12_LimitedRange + | Self::Y_U_V12_FullRange + | Self::Y_U_V16_LimitedRange + | Self::Y_U_V16_FullRange + // TODO(andreas): Y8 isn't really color, does this even make sense? + | Self::Y8_FullRange + | Self::Y8_LimitedRange => ColorPrimaries::Bt709, + + Self::NV12 | Self::YUY2 => ColorPrimaries::Bt601, + } + } + /// Random-access decoding of a specific pixel of an image. /// /// Return `None` if out-of-range. #[inline] pub fn decode_rgb_at(&self, buf: &[u8], [w, h]: [u32; 2], [x, y]: [u32; 2]) -> Option<[u8; 3]> { let [y, u, v] = self.decode_yuv_at(buf, [w, h], [x, y])?; - Some(rgb_from_yuv(y, u, v)) + Some(rgb_from_yuv( + y, + u, + v, + self.is_limited_yuv_range(), + self.color_primaries(), + )) } } diff --git a/crates/store/re_types/src/image.rs b/crates/store/re_types/src/image.rs index 7931a9bf6fe6..a27b541492d2 100644 --- a/crates/store/re_types/src/image.rs +++ b/crates/store/re_types/src/image.rs @@ -266,29 +266,87 @@ fn test_find_non_empty_dim_indices() { // ---------------------------------------------------------------------------- -// TODO(jan): there is a duplicate of this function in `crates/store/re_video/src/decode/av1.rs` +// TODO(andreas): Expose this in the API. +/// Type of color primaries a given image is in. +/// +/// This applies both to YUV and RGB formats, but if not specified otherwise +/// we assume BT.709 primaries for all RGB(A) 8bits per channel content. +#[derive(Clone, Copy, Debug)] +pub enum ColorPrimaries { + /// BT.601 (aka. SDTV, aka. Rec.601) + /// + /// Wiki: + Bt601, + + /// BT.709 (aka. HDTV, aka. Rec.709) + /// + /// Wiki: + /// + /// These are the same primaries we usually assume and use for all of Rerun's rendering + /// since they are the same primaries used by sRGB. + /// + /// The OETF/EOTF function () is different, + /// but for all other purposes they are the same. + /// (The only reason for us to convert to optical units ("linear" instead of "gamma") is for + /// lighting computation & tonemapping where we typically start out with sRGB anyways!) + Bt709, + // + // Not yet supported. These vary a lot more from the other two! + // + // /// BT.2020 (aka. PQ, aka. Rec.2020) + // /// + // /// Wiki: + // BT2020_ConstantLuminance, + // BT2020_NonConstantLuminance, +} + /// Returns sRGB from YUV color. /// -/// This conversion mirrors the function of the same name in `crates/viewer/re_renderer/shader/decodings.wgsl` +/// This conversion mirrors the function of the same name in `yuv_converter.wgsl` /// /// Specifying the color standard should be exposed in the future [#3541](https://github.com/rerun-io/rerun/pull/3541) -pub fn rgb_from_yuv(y: u8, u: u8, v: u8) -> [u8; 3] { - let (y, u, v) = (y as f32, u as f32, v as f32); +pub fn rgb_from_yuv( + y: u8, + u: u8, + v: u8, + limited_range: bool, + primaries: ColorPrimaries, +) -> [u8; 3] { + let (mut y, mut u, mut v) = (y as f32, u as f32, v as f32); // rescale YUV values - let y = (y - 16.0) / 219.0; - let u = (u - 128.0) / 224.0; - let v = (v - 128.0) / 224.0; - - // BT.601 (aka. SDTV, aka. Rec.601). wiki: https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion - let r = y + 1.402 * v; - let g = y - 0.344 * u - 0.714 * v; - let b = y + 1.772 * u; - - // BT.709 (aka. HDTV, aka. Rec.709). wiki: https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.709_conversion - // let r = y + 1.575 * v; - // let g = y - 0.187 * u - 0.468 * v; - // let b = y + 1.856 * u; + if limited_range { + // Via https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion: + // "The resultant signals range from 16 to 235 for Y′ (Cb and Cr range from 16 to 240); + // the values from 0 to 15 are called footroom, while the values from 236 to 255 are called headroom." + y = (y - 16.0) / 219.0; + u = (u - 128.0) / 224.0; + v = (v - 128.0) / 224.0; + } else { + y /= 255.0; + u = (u - 128.0) / 255.0; + v = (v - 128.0) / 255.0; + } + + let r; + let g; + let b; + + match primaries { + ColorPrimaries::Bt601 => { + // BT.601 (aka. SDTV, aka. Rec.601). wiki: https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion + r = y + 1.402 * v; + g = y - 0.344 * u - 0.714 * v; + b = y + 1.772 * u; + } + + ColorPrimaries::Bt709 => { + // BT.709 (aka. HDTV, aka. Rec.709). wiki: https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.709_conversion + r = y + 1.575 * v; + g = y - 0.187 * u - 0.468 * v; + b = y + 1.856 * u; + } + } [(255.0 * r) as u8, (255.0 * g) as u8, (255.0 * b) as u8] } diff --git a/crates/store/re_types/src/testing/datatypes/enum_test.rs b/crates/store/re_types/src/testing/datatypes/enum_test.rs index 930cb17f7185..a8417db68617 100644 --- a/crates/store/re_types/src/testing/datatypes/enum_test.rs +++ b/crates/store/re_types/src/testing/datatypes/enum_test.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types/src/testing/datatypes/valued_enum.rs b/crates/store/re_types/src/testing/datatypes/valued_enum.rs index 0b11ca9c7473..66063d1121b2 100644 --- a/crates/store/re_types/src/testing/datatypes/valued_enum.rs +++ b/crates/store/re_types/src/testing/datatypes/valued_enum.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/store/re_types_blueprint/src/blueprint/components/container_kind.rs b/crates/store/re_types_blueprint/src/blueprint/components/container_kind.rs index 46c3bc33fddb..4aecdd82322f 100644 --- a/crates/store/re_types_blueprint/src/blueprint/components/container_kind.rs +++ b/crates/store/re_types_blueprint/src/blueprint/components/container_kind.rs @@ -11,6 +11,7 @@ #![allow(clippy::redundant_closure)] #![allow(clippy::too_many_arguments)] #![allow(clippy::too_many_lines)] +#![allow(non_camel_case_types)] use ::re_types_core::external::arrow2; use ::re_types_core::ComponentName; diff --git a/crates/viewer/re_renderer/shader/conversions/yuv_converter.wgsl b/crates/viewer/re_renderer/shader/conversions/yuv_converter.wgsl index 1f6d0701be20..29e81a5030f2 100644 --- a/crates/viewer/re_renderer/shader/conversions/yuv_converter.wgsl +++ b/crates/viewer/re_renderer/shader/conversions/yuv_converter.wgsl @@ -2,9 +2,12 @@ #import <../screen_triangle_vertex.wgsl> struct UniformBuffer { - format: u32, + yuv_layout: u32, primaries: u32, target_texture_size: vec2u, + yuv_range: u32, + + _padding: vec3f, // Satisfy `DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED` }; @group(0) @binding(0) @@ -13,24 +16,59 @@ var uniform_buffer: UniformBuffer; @group(0) @binding(1) var input_texture: texture_2d; +// see `enum YuvPixelLayout`. +const YUV_LAYOUT_Y_U_V444 = 0u; +const YUV_LAYOUT_Y_U_V422 = 1u; +const YUV_LAYOUT_Y_U_V420 = 2u; +const YUV_LAYOUT_Y_UV420 = 100u; +const YUV_LAYOUT_YUYV422 = 200u; +const YUV_LAYOUT_Y400 = 300u; -const YUV_LAYOUT_Y_UV = 0u; -const YUV_LAYOUT_YUYV16 = 1u; - +// see `enum ColorPrimaries`. const PRIMARIES_BT601 = 0u; const PRIMARIES_BT709 = 1u; +// see `enum YuvRange`. +const YUV_RANGE_LIMITED = 0u; +const YUV_RANGE_FULL = 1u; + /// Returns sRGB from YUV color. /// /// This conversion mirrors the function in `crates/store/re_types/src/datatypes/tensor_data_ext.rs` /// /// Specifying the color standard should be exposed in the future [#3541](https://github.com/rerun-io/rerun/pull/3541) -fn srgb_from_yuv(yuv: vec3f, primaries: u32) -> vec3f { +fn srgb_from_yuv(yuv: vec3f, primaries: u32, range: u32) -> vec3f { // rescale YUV values - let y = (yuv[0] - 16.0) / 219.0; - let u = (yuv[1] - 128.0) / 224.0; - let v = (yuv[2] - 128.0) / 224.0; + // + // This is what is called "limited range" and is the most common case. + // TODO(andreas): Support "full range" as well. + + var y: f32; + var u: f32; + var v: f32; + + switch (range) { + case YUV_RANGE_LIMITED: { + // Via https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion: + // "The resultant signals range from 16 to 235 for Y′ (Cb and Cr range from 16 to 240); + // the values from 0 to 15 are called footroom, while the values from 236 to 255 are called headroom." + y = (yuv[0] - 16.0) / 219.0; + u = (yuv[1] - 128.0) / 224.0; + v = (yuv[2] - 128.0) / 224.0; + } + + case YUV_RANGE_FULL: { + y = yuv[0] / 255.0; + u = (yuv[1] - 128.0) / 255.0; + v = (yuv[2] - 128.0) / 255.0; + } + + default: { + // Should never happen. + return ERROR_RGBA.rgb; + } + } var rgb: vec3f; @@ -53,7 +91,7 @@ fn srgb_from_yuv(yuv: vec3f, primaries: u32) -> vec3f { } default: { - rgb = ERROR_RGBA.rgb; + return ERROR_RGBA.rgb; } } @@ -64,27 +102,70 @@ fn srgb_from_yuv(yuv: vec3f, primaries: u32) -> vec3f { /// /// See also `enum YuvPixelLayout` in `yuv_converter.rs for a specification of /// the expected data layout. -fn sample_yuv(yuv_layout: u32, texture: texture_2d, coords: vec2f) -> vec3f { +fn sample_yuv(yuv_layout: u32, texture: texture_2d, coords: vec2u, target_texture_size: vec2u) -> vec3f { let texture_dim = vec2f(textureDimensions(texture).xy); var yuv: vec3f; switch (yuv_layout) { - case YUV_LAYOUT_Y_UV: { + case YUV_LAYOUT_Y_U_V444: { + // Just 3 planes under each other. + yuv[0] = f32(textureLoad(texture, coords, 0).r); + yuv[1] = f32(textureLoad(texture, vec2u(coords.x, coords.y + target_texture_size.y), 0).r); + yuv[2] = f32(textureLoad(texture, vec2u(coords.x, coords.y + target_texture_size.y * 2u), 0).r); + } + + case YUV_LAYOUT_Y_U_V422: { + // A large Y plane, followed by a UV plane with half the horizontal resolution, + // every row contains two u/v rows. + yuv[0] = f32(textureLoad(texture, coords, 0).r); + // UV coordinate on its own plane: + let uv_coord = vec2u(coords.x / 2u, coords.y); + // UV coordinate on the data texture, ignoring offset from previous planes. + // Each texture row contains two UV rows + let uv_col = uv_coord.x + (uv_coord.y % 2) * target_texture_size.x / 2u; + let uv_row = uv_coord.y / 2u; + + yuv[1] = f32(textureLoad(texture, vec2u(uv_col, uv_row + target_texture_size.y), 0).r); + yuv[2] = f32(textureLoad(texture, vec2u(uv_col, uv_row + target_texture_size.y + target_texture_size.y / 2u), 0).r); + } + + case YUV_LAYOUT_Y_U_V420: { + // A large Y plane, followed by a UV plane with half the horizontal & vertical resolution, + // every row contains two u/v rows and there's only half as many. + yuv[0] = f32(textureLoad(texture, coords, 0).r); + // UV coordinate on its own plane: + let uv_coord = vec2u(coords.x / 2u, coords.y / 2u); + // UV coordinate on the data texture, ignoring offset from previous planes. + // Each texture row contains two UV rows + let uv_col = uv_coord.x + (uv_coord.y % 2) * (target_texture_size.x / 2u); + let uv_row = uv_coord.y / 2u; + + yuv[1] = f32(textureLoad(texture, vec2u(uv_col, uv_row + target_texture_size.y), 0).r); + yuv[2] = f32(textureLoad(texture, vec2u(uv_col, uv_row + target_texture_size.y + target_texture_size.y / 4u), 0).r); + } + + case YUV_LAYOUT_Y400 { + yuv[0] = f32(textureLoad(texture, coords, 0).r); + yuv[1] = 128.0; + yuv[2] = 128.0; + } + + case YUV_LAYOUT_Y_UV420: { let uv_offset = u32(floor(texture_dim.y / 1.5)); - let uv_row = u32(coords.y / 2); - var uv_col = u32(coords.x / 2) * 2u; + let uv_row = (coords.y / 2u); + var uv_col = (coords.x / 2u) * 2u; - yuv[0] = f32(textureLoad(texture, vec2u(coords), 0).r); - yuv[1] = f32(textureLoad(texture, vec2u(u32(uv_col), uv_offset + uv_row), 0).r); - yuv[2] = f32(textureLoad(texture, vec2u((u32(uv_col) + 1u), uv_offset + uv_row), 0).r); + yuv[0] = f32(textureLoad(texture, coords, 0).r); + yuv[1] = f32(textureLoad(texture, vec2u(uv_col, uv_offset + uv_row), 0).r); + yuv[2] = f32(textureLoad(texture, vec2u((uv_col + 1u), uv_offset + uv_row), 0).r); } - case YUV_LAYOUT_YUYV16: { + case YUV_LAYOUT_YUYV422: { // texture is 2 * width * height // every 4 bytes is 2 pixels - let uv_row = u32(coords.y); + let uv_row = coords.y; // multiply by 2 because the width is multiplied by 2 - let y_col = u32(coords.x) * 2u; + let y_col = coords.x * 2u; yuv[0] = f32(textureLoad(texture, vec2u(y_col, uv_row), 0).r); // at odd pixels we're in the second half of the yuyu block, offset back by 2 @@ -103,10 +184,10 @@ fn sample_yuv(yuv_layout: u32, texture: texture_2d, coords: vec2f) -> vec3f @fragment fn fs_main(in: FragmentInput) -> @location(0) vec4f { - let coords = vec2f(uniform_buffer.target_texture_size) * in.texcoord; + let coords = vec2u(vec2f(uniform_buffer.target_texture_size) * in.texcoord); - let yuv = sample_yuv(uniform_buffer.format, input_texture, coords); - let rgb = srgb_from_yuv(yuv, uniform_buffer.primaries); + let yuv = sample_yuv(uniform_buffer.yuv_layout, input_texture, coords, uniform_buffer.target_texture_size); + let rgb = srgb_from_yuv(yuv, uniform_buffer.primaries, uniform_buffer.yuv_range); return vec4f(rgb, 1.0); } diff --git a/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs b/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs index 42d79c78ecf7..1ba94392a9ac 100644 --- a/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs +++ b/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs @@ -1,4 +1,4 @@ -use super::yuv_converter::{YuvFormatConversionTask, YuvPixelLayout}; +use super::yuv_converter::{YuvFormatConversionTask, YuvPixelLayout, YuvRange}; use crate::{ renderer::DrawError, wgpu_resources::{GpuTexture, TextureDesc}, @@ -12,7 +12,7 @@ use crate::{ /// Since with YUV content the color space is often less clear, we always explicitly /// specify it. /// -/// Ffmpeg's documentation has a short & good overview of these relationships: +/// Ffmpeg's documentation has a short & good overview of the relationship of YUV & color primaries: /// /// /// Values need to be kept in sync with `yuv_converter.wgsl` @@ -34,7 +34,7 @@ pub enum ColorPrimaries { /// but for all other purposes they are the same. /// (The only reason for us to convert to optical units ("linear" instead of "gamma") is for /// lighting & tonemapping where we typically start out with an sRGB image!) - Bt709 = 2, + Bt709 = 1, // // Not yet supported. These vary a lot more from the other two! // @@ -46,9 +46,6 @@ pub enum ColorPrimaries { } /// Image data format that can be converted to a wgpu texture. -/// -/// Names follow a similar convention as Facebook's Ocean library -/// See // TODO(andreas): Right now this combines both color space and pixel format. Consider separating them similar to how we do on user facing APIs. #[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug)] @@ -65,6 +62,7 @@ pub enum SourceImageDataFormat { Yuv { format: YuvPixelLayout, primaries: ColorPrimaries, + range: YuvRange, }, // // TODO(#7608): Add rgb (3 channels!) formats. @@ -262,9 +260,14 @@ pub fn transfer_image_data_to_texture( // No further conversion needed, we're done here! return Ok(data_texture); } - SourceImageDataFormat::Yuv { format, primaries } => YuvFormatConversionTask::new( + SourceImageDataFormat::Yuv { + format, + primaries, + range, + } => YuvFormatConversionTask::new( ctx, format, + range, primaries, &data_texture, &label, diff --git a/crates/viewer/re_renderer/src/resource_managers/mod.rs b/crates/viewer/re_renderer/src/resource_managers/mod.rs index 6bbab468f8b6..c3210fc9e034 100644 --- a/crates/viewer/re_renderer/src/resource_managers/mod.rs +++ b/crates/viewer/re_renderer/src/resource_managers/mod.rs @@ -14,4 +14,4 @@ pub use image_data_to_texture::{ ColorPrimaries, ImageDataDesc, ImageDataToTextureError, SourceImageDataFormat, }; pub use texture_manager::{GpuTexture2D, TextureManager2D, TextureManager2DError}; -pub use yuv_converter::YuvPixelLayout; +pub use yuv_converter::{YuvPixelLayout, YuvRange}; diff --git a/crates/viewer/re_renderer/src/resource_managers/yuv_converter.rs b/crates/viewer/re_renderer/src/resource_managers/yuv_converter.rs index a72a632e51ce..075c24f13ccb 100644 --- a/crates/viewer/re_renderer/src/resource_managers/yuv_converter.rs +++ b/crates/viewer/re_renderer/src/resource_managers/yuv_converter.rs @@ -15,13 +15,108 @@ use super::ColorPrimaries; /// Supported chroma subsampling input formats. /// +/// We use `YUV`/`YCbCr`/`YPbPr` interchangeably and usually just call it `YUV`. +/// +/// According to this [source](https://www.retrosix.wiki/yuv-vs-ycbcr-vs-rgb-color-space/): +/// * `YUV` is an analog signal +/// * `YCbCr` is scaled and offsetted version of YUV, used in digital signals (we denote this as "limited range YUV") +/// * `YPbPr` is the physical component cabel to transmit `YCbCr` +/// Actual use in the wild seems to be all over the place. +/// For instance `OpenCV` uses `YCbCr` when talking about the full range and YUV when talking about +/// limited range. [Source](https://docs.opencv.org/4.x/de/d25/imgproc_color_conversions.html): +/// > RGB <-> YCrCb JPEG [...] Y, Cr, and Cb cover the whole value range. +/// > RGB <-> YUV with subsampling [...] with resulting values Y [16, 235], U and V [16, 240] centered at 128. +/// +/// For more on YUV ranges see [`YuvRange`]. +/// +/// Naming schema: +/// * every time a plane starts add a `_` +/// * end with `4xy` for 4:x:y subsampling. +/// +/// This picture gives a great overview of how to interpret the 4:x:y naming scheme for subsampling: +/// +/// /// Keep indices in sync with `yuv_converter.wgsl` #[allow(non_camel_case_types)] #[derive(Clone, Copy, Debug)] pub enum YuvPixelLayout { + // --------------------------- + // Planar formats + // --------------------------- + // + /// 4:4:4 no chroma downsampling with 3 separate planes. + /// Also known as `I444` + /// + /// Expects single channel data texture format. + /// + /// ```text + /// width + /// __________ + /// | | + /// height | Y | + /// | | + /// |_________| + /// | | + /// height | U | + /// | | + /// |_________| + /// | | + /// height | V | + /// | | + /// |_________| + /// ``` + Y_U_V444 = 0, + + /// 4:2:2 subsampling with 3 separate planes. + /// Also known as `I422` + /// + /// Expects single channel data texture format. + /// + /// Each data texture row in U & V section contains two rows + /// of U/V respectively, since there's a total of (width/2) * (height/2) U & V samples + /// + /// ```text + /// width + /// __________ + /// | | + /// height | Y | + /// | | + /// |_________| + /// height/2 | U | + /// |_________| + /// height/2 | V | + /// |_________| + /// ``` + Y_U_V422 = 1, + + /// 4:2:0 subsampling with 3 separate planes. + /// Also known as `I420` + /// + /// Expects single channel data texture format. + /// + /// Each data texture row in U & V section contains two rows + /// of U/V respectively, since there's a total of (width/2) * height U & V samples + /// + /// ```text + /// width + /// __________ + /// | | + /// height | Y | + /// | | + /// |_________| + /// height/4 |___◌̲U____| + /// height/4 |___◌̲V____| + /// ``` + Y_U_V420 = 2, + + // --------------------------- + // Semi-planar formats + // --------------------------- + // /// 4:2:0 subsampling with a separate Y plane, followed by a UV plane. + /// Also known as `NV12` (although `NV12` usually also implies the limited range). /// - /// Expects single channel texture format. + /// Expects single channel data texture format. /// /// First comes entire image in Y in one plane, /// followed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc. @@ -36,11 +131,15 @@ pub enum YuvPixelLayout { /// height/2 | U,V,U,… | /// |_________| /// ``` - Y_UV12 = 0, + Y_UV420 = 100, + // --------------------------- + // Interleaved formats + // --------------------------- + // /// YUV 4:2:2 subsampling, single plane. /// - /// Expects single channel texture format. + /// Expects single channel data texture format. /// /// The order of the channels is Y0, U0, Y1, V0, all in the same plane. /// @@ -51,15 +150,57 @@ pub enum YuvPixelLayout { /// height | Y0, U0, Y1, V0… | /// |_________________| /// ``` - YUYV16 = 1, + YUYV422 = 200, + + // --------------------------- + // Monochrome formats + // --------------------------- + // + /// 4:0:0, single plane of chroma only. + /// Also known as I400 + /// + /// Expects single channel data texture format. + /// + /// Note that we still convert this to RGBA, for convenience. + /// + /// ```text + /// width + /// __________ + /// | | + /// height | Y | + /// | | + /// |_________| + /// ``` + Y400 = 300, +} + +/// Expected range of YUV values. +/// +/// Keep indices in sync with `yuv_converter.wgsl` +#[derive(Clone, Copy, Debug, Default)] +pub enum YuvRange { + /// Use limited range YUV, i.e. for 8bit data, Y is valid in [16, 235] and U/V [16, 240]. + /// + /// This is by far the more common YUV range. + // TODO(andreas): What about higher bit ranges? + // This range says https://www.reddit.com/r/ffmpeg/comments/uiugfc/comment/i7f4wyp/ + // 64-940 for Y and 64-960 for chroma. + #[default] + Limited = 0, + + /// Use full range YUV with all components ranging from 0 to 255 for 8bit or higher otherwise. + Full = 1, } impl YuvPixelLayout { /// Given the dimensions of the output picture, what are the expected dimensions of the input data texture. pub fn data_texture_width_height(&self, [decoded_width, decoded_height]: [u32; 2]) -> [u32; 2] { match self { - Self::Y_UV12 => [decoded_width, decoded_height + decoded_height / 2], - Self::YUYV16 => [decoded_width * 2, decoded_height], + Self::Y_U_V444 => [decoded_width, decoded_height * 3], + Self::Y_U_V422 => [decoded_width, decoded_height * 2], + Self::Y_U_V420 | Self::Y_UV420 => [decoded_width, decoded_height + decoded_height / 2], + Self::YUYV422 => [decoded_width * 2, decoded_height], + Self::Y400 => [decoded_width, decoded_height], } } @@ -70,24 +211,36 @@ impl YuvPixelLayout { // Our shader currently works with 8 bit integer formats here since while // _technically_ YUV formats have nothing to do with concrete bit depth, // practically there's underlying expectation for 8 bits per channel - // as long as the data is Bt.709 or Bt.601. + // at least as long as the data is Bt.709 or Bt.601. // In other words: The conversions implementations we have today expect 0-255 as the value range. #[allow(clippy::match_same_arms)] match self { - Self::Y_UV12 => wgpu::TextureFormat::R8Uint, + // Only thing that makes sense for 8 bit planar data is the R8Uint format. + Self::Y_U_V444 | Self::Y_U_V422 | Self::Y_U_V420 => wgpu::TextureFormat::R8Uint, + + // Same for planar + Self::Y_UV420 => wgpu::TextureFormat::R8Uint, + + // Interleaved have opportunities here! // TODO(andreas): Why not use [`wgpu::TextureFormat::Rg8Uint`] here? - Self::YUYV16 => wgpu::TextureFormat::R8Uint, + Self::YUYV422 => wgpu::TextureFormat::R8Uint, + + // Monochrome have only one channel anyways. + Self::Y400 => wgpu::TextureFormat::R8Uint, } } /// Size of the buffer needed to create the data texture, i.e. the raw input data. pub fn num_data_buffer_bytes(&self, decoded_width: [u32; 2]) -> usize { - let num_pixels = decoded_width[0] as usize * decoded_width[1] as usize; - match self { - Self::Y_UV12 => 12 * num_pixels / 8, - Self::YUYV16 => 16 * num_pixels / 8, - } + let data_texture_width_height = self.data_texture_width_height(decoded_width); + let data_texture_format = self.data_texture_format(); + + (data_texture_format + .block_copy_size(None) + .expect("data texture formats are expected to be trivial") + * data_texture_width_height[0] + * data_texture_width_height[1]) as usize } } @@ -98,14 +251,17 @@ mod gpu_data { #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] pub struct UniformBuffer { /// Uses [`super::YuvPixelLayout`]. - pub pixel_layout: u32, + pub yuv_layout: u32, /// Uses [`super::ColorPrimaries`]. pub primaries: u32, pub target_texture_size: [u32; 2], - pub _end_padding: [wgpu_buffer_types::PaddingRow; 16 - 1], + /// Uses [`super::YuvRange`]. + pub yuv_range: wgpu_buffer_types::U32RowPadded, + + pub _end_padding: [wgpu_buffer_types::PaddingRow; 16 - 2], } } @@ -132,7 +288,8 @@ impl YuvFormatConversionTask { /// see methods of [`YuvPixelLayout`] for details. pub fn new( ctx: &RenderContext, - format: YuvPixelLayout, + yuv_layout: YuvPixelLayout, + yuv_range: YuvRange, primaries: ColorPrimaries, input_data: &GpuTexture, output_label: &DebugLabel, @@ -163,9 +320,10 @@ impl YuvFormatConversionTask { ctx, format!("{output_label}_conversion").into(), gpu_data::UniformBuffer { - pixel_layout: format as _, + yuv_layout: yuv_layout as _, primaries: primaries as _, target_texture_size: output_width_height, + yuv_range: (yuv_range as u32).into(), _end_padding: Default::default(), }, diff --git a/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs b/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs index e093a3edd121..ba6f0907fb2e 100644 --- a/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs +++ b/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs @@ -10,7 +10,9 @@ use re_renderer::{ config::DeviceCaps, pad_rgb_to_rgba, renderer::{ColorMapper, ColormappedTexture, ShaderDecoding}, - resource_managers::{ColorPrimaries, ImageDataDesc, SourceImageDataFormat, YuvPixelLayout}, + resource_managers::{ + ColorPrimaries, ImageDataDesc, SourceImageDataFormat, YuvPixelLayout, YuvRange, + }, RenderContext, }; use re_types::components::ClassId; @@ -188,11 +190,9 @@ pub fn image_data_range_heuristic(image_stats: &ImageStats, image_format: &Image /// Return whether an image should be assumed to be encoded in sRGB color space ("gamma space", no EOTF applied). fn image_decode_srgb_gamma_heuristic(image_stats: &ImageStats, image_format: ImageFormat) -> bool { - if let Some(pixel_format) = image_format.pixel_format { - match pixel_format { - // Have to do the conversion because we don't use an `Srgb` texture format. - PixelFormat::NV12 | PixelFormat::YUY2 => true, - } + if image_format.pixel_format.is_some() { + // Have to do the conversion because we don't use an `Srgb` texture format. + true } else { let (min, max) = image_stats.finite_range; @@ -247,25 +247,70 @@ pub fn texture_creation_desc_from_color_image<'a>( // TODO(#7608): All image data ingestion conversions should all be handled by re_renderer! let (data, format) = if let Some(pixel_format) = image.format.pixel_format { - match pixel_format { - // Using Bt.601 here for historical reasons. + let data = cast_slice_to_cow(image.buffer.as_slice()); + let primaries = match pixel_format.color_primaries() { + re_types::image::ColorPrimaries::Bt601 => ColorPrimaries::Bt601, + re_types::image::ColorPrimaries::Bt709 => ColorPrimaries::Bt709, + }; + + let range = match pixel_format.is_limited_yuv_range() { + true => YuvRange::Limited, + false => YuvRange::Full, + }; + + let format = match pixel_format { + // For historical reasons, using Bt.709 for fully planar formats and Bt.601 for others. + // + // TODO(andreas): Investigate if there's underlying expectation for some of these (for instance I suspect that NV12 is "usually" BT601). // TODO(andreas): Expose color primaries. It's probably still the better default (for instance that's what jpeg still uses), // but should confirm & back that up! - PixelFormat::NV12 => ( - cast_slice_to_cow(image.buffer.as_slice()), + // + PixelFormat::Y_U_V24_FullRange | PixelFormat::Y_U_V24_LimitedRange => { SourceImageDataFormat::Yuv { - format: YuvPixelLayout::Y_UV12, - primaries: ColorPrimaries::Bt601, - }, - ), - PixelFormat::YUY2 => ( - cast_slice_to_cow(image.buffer.as_slice()), + format: YuvPixelLayout::Y_U_V444, + range, + primaries, + } + } + + PixelFormat::Y_U_V16_FullRange | PixelFormat::Y_U_V16_LimitedRange => { SourceImageDataFormat::Yuv { - format: YuvPixelLayout::YUYV16, - primaries: ColorPrimaries::Bt601, - }, - ), - } + format: YuvPixelLayout::Y_U_V422, + range, + primaries, + } + } + + PixelFormat::Y_U_V12_FullRange | PixelFormat::Y_U_V12_LimitedRange => { + SourceImageDataFormat::Yuv { + format: YuvPixelLayout::Y_U_V420, + range, + primaries, + } + } + + PixelFormat::Y8_FullRange | PixelFormat::Y8_LimitedRange => { + SourceImageDataFormat::Yuv { + format: YuvPixelLayout::Y400, + range, + primaries, + } + } + + PixelFormat::NV12 => SourceImageDataFormat::Yuv { + format: YuvPixelLayout::Y_UV420, + range, + primaries, + }, + + PixelFormat::YUY2 => SourceImageDataFormat::Yuv { + format: YuvPixelLayout::YUYV422, + range, + primaries, + }, + }; + + (data, format) } else { let color_model = image.format.color_model(); let datatype = image.format.datatype(); diff --git a/crates/viewer/re_viewer_context/src/image_info.rs b/crates/viewer/re_viewer_context/src/image_info.rs index 56f5032d2271..6a19d2f0876f 100644 --- a/crates/viewer/re_viewer_context/src/image_info.rs +++ b/crates/viewer/re_viewer_context/src/image_info.rs @@ -99,7 +99,13 @@ impl ImageInfo { // Shouldn't hit BGR and BGRA, but we'll handle it like RGB and RGBA here for completeness. ColorModel::RGB | ColorModel::RGBA | ColorModel::BGR | ColorModel::BGRA => { if channel < 3 { - let rgb = rgb_from_yuv(luma, u, v); + let rgb = rgb_from_yuv( + luma, + u, + v, + pixel_format.is_limited_yuv_range(), + pixel_format.color_primaries(), + ); Some(TensorElement::U8(rgb[channel as usize])) } else if channel == 4 { Some(TensorElement::U8(255)) diff --git a/crates/viewer/re_viewer_context/src/tensor/image_stats.rs b/crates/viewer/re_viewer_context/src/tensor/image_stats.rs index c4254feb78fe..7b453babf0a1 100644 --- a/crates/viewer/re_viewer_context/src/tensor/image_stats.rs +++ b/crates/viewer/re_viewer_context/src/tensor/image_stats.rs @@ -1,6 +1,6 @@ use half::f16; -use re_types::datatypes::{ChannelDatatype, PixelFormat}; +use re_types::datatypes::ChannelDatatype; use crate::ImageInfo; @@ -121,8 +121,11 @@ impl ImageStats { // --------------------------- let datatype = match image.format.pixel_format { - Some(PixelFormat::NV12 | PixelFormat::YUY2) => { - // We do the lazy thing here: + Some(_) => { + // We do the lazy thing here since we convert everything to RGB8 right now anyways. + // Note that this range is all about the format we're converting _to_. + // It would be nice if we can distininguish this better in the future: + // E.g. limited range YUV should have the correct limited range. return Self { range: Some((0.0, 255.0)), finite_range: (0.0, 255.0), diff --git a/docs/content/reference/types/datatypes/pixel_format.md b/docs/content/reference/types/datatypes/pixel_format.md index 6464475e6be0..636d22c441c6 100644 --- a/docs/content/reference/types/datatypes/pixel_format.md +++ b/docs/content/reference/types/datatypes/pixel_format.md @@ -17,8 +17,16 @@ For more compressed image formats, see [`archetypes.EncodedImage`](https://rerun ## Variants +* Y_U_V12_LimitedRange * NV12 * YUY2 +* Y8_FullRange +* Y_U_V24_LimitedRange +* Y_U_V24_FullRange +* Y8_LimitedRange +* Y_U_V12_FullRange +* Y_U_V16_LimitedRange +* Y_U_V16_FullRange ## API reference links * 🌊 [C++ API docs for `PixelFormat`](https://ref.rerun.io/docs/cpp/stable/namespacererun_1_1datatypes.html) diff --git a/rerun_cpp/src/rerun/datatypes/pixel_format.hpp b/rerun_cpp/src/rerun/datatypes/pixel_format.hpp index 1cd791004b7b..37844ae73751 100644 --- a/rerun_cpp/src/rerun/datatypes/pixel_format.hpp +++ b/rerun_cpp/src/rerun/datatypes/pixel_format.hpp @@ -33,16 +33,85 @@ namespace rerun::datatypes { /// For more compressed image formats, see `archetypes::EncodedImage`. enum class PixelFormat : uint8_t { - /// `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled format with 12 bits per pixel and 8 bits per channel. + /// `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the resolution of the Y plane. + Y_U_V12_LimitedRange = 20, + + /// `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled form at with 12 bits per pixel and 8 bits per channel. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. /// /// First comes entire image in Y in one plane, /// followed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc. NV12 = 26, - /// `YUY2` (aka `YUYV` or `YUYV16`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. + /// `YUY2` (aka `YUYV`, `YUYV16` or `NV21`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. /// /// The order of the channels is Y0, U0, Y1, V0, all in the same plane. YUY2 = 27, + + /// Monochrome Y plane only, essentially a YUV 4:0:0 planar format. + /// + /// Also known as just "gray". This is virtually identical to a 8bit luminance/grayscale (see `datatypes::ColorModel`). + /// + /// This uses entire range YUV, i.e. Y is expected to be within [0, 255]. + /// (as opposed to "limited range" YUV as used e.g. in NV12). + Y8_FullRange = 30, + + /// `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes. + Y_U_V24_LimitedRange = 39, + + /// `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes. + Y_U_V24_FullRange = 40, + + /// Monochrome Y plane only, essentially a YUV 4:0:0 planar format. + /// + /// Also known as just "gray". + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235]. + /// If not for this range limitation/remapping, this is almost identical to 8bit luminace/grayscale (see `datatypes::ColorModel`). + Y8_LimitedRange = 41, + + /// `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the resolution of the Y plane. + Y_U_V12_FullRange = 44, + + /// `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. + /// + /// This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the horizontal resolution of the Y plane. + Y_U_V16_LimitedRange = 49, + + /// `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. + /// + /// This uses full range YUV with all components ranging from 0 to 255 + /// (as opposed to "limited range" YUV as used e.g. in NV12). + /// + /// First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + /// the horizontal resolution of the Y plane. + Y_U_V16_FullRange = 50, }; } // namespace rerun::datatypes diff --git a/rerun_cpp/src/rerun/image_utils.hpp b/rerun_cpp/src/rerun/image_utils.hpp index 12be1ece918c..de78d531ebf0 100644 --- a/rerun_cpp/src/rerun/image_utils.hpp +++ b/rerun_cpp/src/rerun/image_utils.hpp @@ -152,10 +152,27 @@ namespace rerun { ) { auto num_pixels = resolution.width * resolution.height; switch (pixel_format) { + // 444 formats. + case datatypes::PixelFormat::Y_U_V24_FullRange: + case datatypes::PixelFormat::Y_U_V24_LimitedRange: + return num_pixels * 4; + + // 422 formats. + case datatypes::PixelFormat::Y_U_V16_FullRange: + case datatypes::PixelFormat::Y_U_V16_LimitedRange: case datatypes::PixelFormat::NV12: - return 12 * num_pixels / 8; - case datatypes::PixelFormat::YUY2: return 16 * num_pixels / 8; + + // 420 formats. + case datatypes::PixelFormat::Y_U_V12_FullRange: + case datatypes::PixelFormat::Y_U_V12_LimitedRange: + case datatypes::PixelFormat::YUY2: + return 12 * num_pixels / 8; + + // Monochrome formats. + case datatypes::PixelFormat::Y8_LimitedRange: + case datatypes::PixelFormat::Y8_FullRange: + return num_pixels; } return 0; } diff --git a/rerun_py/rerun_sdk/rerun/datatypes/pixel_format.py b/rerun_py/rerun_sdk/rerun/datatypes/pixel_format.py index 872f076901b5..5ea053f8bdae 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/pixel_format.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/pixel_format.py @@ -35,9 +35,21 @@ class PixelFormat(Enum): For more compressed image formats, see [`archetypes.EncodedImage`][rerun.archetypes.EncodedImage]. """ + Y_U_V12_LimitedRange = 20 + """ + `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. + + This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + + First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + the resolution of the Y plane. + """ + NV12 = 26 """ - `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled format with 12 bits per pixel and 8 bits per channel. + `NV12` (aka `Y_UV12`) is a YUV 4:2:0 chroma downsampled form at with 12 bits per pixel and 8 bits per channel. + + This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. First comes entire image in Y in one plane, followed by a plane with interleaved lines ordered as U0, V0, U1, V1, etc. @@ -45,11 +57,84 @@ class PixelFormat(Enum): YUY2 = 27 """ - `YUY2` (aka `YUYV` or `YUYV16`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. + `YUY2` (aka `YUYV`, `YUYV16` or `NV21`), is a YUV 4:2:2 chroma downsampled format with 16 bits per pixel and 8 bits per channel. + + This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. The order of the channels is Y0, U0, Y1, V0, all in the same plane. """ + Y8_FullRange = 30 + """ + Monochrome Y plane only, essentially a YUV 4:0:0 planar format. + + Also known as just "gray". This is virtually identical to a 8bit luminance/grayscale (see [`datatypes.ColorModel`][rerun.datatypes.ColorModel]). + + This uses entire range YUV, i.e. Y is expected to be within [0, 255]. + (as opposed to "limited range" YUV as used e.g. in NV12). + """ + + Y_U_V24_LimitedRange = 39 + """ + `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. + + This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + + First comes entire image in Y in one plane, followed by the U and V planes. + """ + + Y_U_V24_FullRange = 40 + """ + `Y_U_V24` is a YUV 4:4:4 fully planar YUV format without chroma downsampling, also known as `I444`. + + This uses full range YUV with all components ranging from 0 to 255 + (as opposed to "limited range" YUV as used e.g. in NV12). + + First comes entire image in Y in one plane, followed by the U and V planes. + """ + + Y8_LimitedRange = 41 + """ + Monochrome Y plane only, essentially a YUV 4:0:0 planar format. + + Also known as just "gray". + + This uses limited range YUV, i.e. Y is expected to be within [16, 235]. + If not for this range limitation/remapping, this is almost identical to 8bit luminace/grayscale (see [`datatypes.ColorModel`][rerun.datatypes.ColorModel]). + """ + + Y_U_V12_FullRange = 44 + """ + `Y_U_V12` is a YUV 4:2:0 fully planar YUV format without chroma downsampling, also known as `I420`. + + This uses full range YUV with all components ranging from 0 to 255 + (as opposed to "limited range" YUV as used e.g. in NV12). + + First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + the resolution of the Y plane. + """ + + Y_U_V16_LimitedRange = 49 + """ + `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. + + This uses limited range YUV, i.e. Y is expected to be within [16, 235] and U/V within [16, 240]. + + First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + the horizontal resolution of the Y plane. + """ + + Y_U_V16_FullRange = 50 + """ + `Y_U_V16` is a YUV 4:2:2 fully planar YUV format without chroma downsampling, also known as `I422`. + + This uses full range YUV with all components ranging from 0 to 255 + (as opposed to "limited range" YUV as used e.g. in NV12). + + First comes entire image in Y in one plane, followed by the U and V planes, which each only have half + the horizontal resolution of the Y plane. + """ + @classmethod def auto(cls, val: str | int | PixelFormat) -> PixelFormat: """Best-effort converter, including a case-insensitive string matcher.""" @@ -71,7 +156,32 @@ def __str__(self) -> str: return self.name -PixelFormatLike = Union[PixelFormat, Literal["NV12", "YUY2", "nv12", "yuy2"], int] +PixelFormatLike = Union[ + PixelFormat, + Literal[ + "NV12", + "Y8_FullRange", + "Y8_LimitedRange", + "YUY2", + "Y_U_V12_FullRange", + "Y_U_V12_LimitedRange", + "Y_U_V16_FullRange", + "Y_U_V16_LimitedRange", + "Y_U_V24_FullRange", + "Y_U_V24_LimitedRange", + "nv12", + "y8_fullrange", + "y8_limitedrange", + "y_u_v12_fullrange", + "y_u_v12_limitedrange", + "y_u_v16_fullrange", + "y_u_v16_limitedrange", + "y_u_v24_fullrange", + "y_u_v24_limitedrange", + "yuy2", + ], + int, +] PixelFormatArrayLike = Union[PixelFormatLike, Sequence[PixelFormatLike]] diff --git a/tests/python/chroma_downsample_image/main.py b/tests/python/chroma_downsample_image/main.py deleted file mode 100755 index 427cf1bff119..000000000000 --- a/tests/python/chroma_downsample_image/main.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python3 -"""Testing NV12 image encoding.""" - -from __future__ import annotations - -import argparse -import os -from typing import Any - -import cv2 -import numpy as np -import rerun as rr -import rerun.blueprint as rrb - - -def bgra2nv12(bgra: Any) -> np.ndarray: - yuv = cv2.cvtColor(bgra, cv2.COLOR_BGRA2YUV_I420) - uv_row_cnt = yuv.shape[0] // 3 - uv_plane = np.transpose(yuv[uv_row_cnt * 2 :].reshape(2, -1), [1, 0]) - yuv[uv_row_cnt * 2 :] = uv_plane.reshape(uv_row_cnt, -1) - return yuv - - -def bgra2yuy2(bgra: Any) -> np.ndarray: - yuv = cv2.cvtColor(bgra, cv2.COLOR_BGRA2YUV_YUY2) - (y, uv) = cv2.split(yuv) - - yuy2 = np.empty((y.shape[0], y.shape[1] * 2), dtype=y.dtype) - yuy2[:, 0::2] = y - yuy2[:, 1::4] = uv[:, ::2] - yuy2[:, 3::4] = uv[:, 1::2] - - return yuy2 - - -def main() -> None: - parser = argparse.ArgumentParser(description="Displaying chroma downsampled images.") - rr.script_add_args(parser) - args = parser.parse_args() - - rr.script_setup( - args, - "rerun_example_chroma_downsampled", - default_blueprint=rrb.Grid( - rrb.Spatial2DView(origin="img_reference", name="Reference RGB"), - rrb.Spatial2DView(origin="img_nv12", name="NV12"), - rrb.Spatial2DView(origin="img_yuy2", name="YUY2"), - rrb.TextDocumentView(origin="expectation", name="expectation"), - ), - ) - - # Make sure you use a colorful image! - dir_path = os.path.dirname(os.path.realpath(__file__)) - img_path = f"{dir_path}/../../../crates/viewer/re_ui/data/logo_dark_mode.png" - img_bgra = cv2.imread(img_path, cv2.IMREAD_UNCHANGED) - - img_rgb = cv2.cvtColor(img_bgra, cv2.COLOR_BGRA2RGB) - rr.log("img_reference", rr.Image(img_rgb, "rgb")) - - rr.log( - "img_nv12", - rr.Image( - width=img_bgra.shape[1], - height=img_bgra.shape[0], - pixel_format=rr.PixelFormat.NV12, - bytes=bgra2nv12(img_bgra).tobytes(), - ), - ) - rr.log( - "img_yuy2", - rr.Image( - width=img_bgra.shape[1], - height=img_bgra.shape[0], - pixel_format=rr.PixelFormat.YUY2, - bytes=bgra2yuy2(img_bgra).tobytes(), - ), - ) - - rr.log("expectation", rr.TextDocument("The images should look the same, except for some chroma artifacts.")) - - rr.script_teardown(args) - - -if __name__ == "__main__": - main() diff --git a/tests/python/chroma_downsample_image/requirements.txt b/tests/python/chroma_downsample_image/requirements.txt deleted file mode 100644 index 4364766d7369..000000000000 --- a/tests/python/chroma_downsample_image/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -numpy -opencv-python -rerun-sdk diff --git a/tests/python/release_checklist/check_chroma_subsampling.py b/tests/python/release_checklist/check_chroma_subsampling.py new file mode 100644 index 000000000000..4cfda9ad5d6c --- /dev/null +++ b/tests/python/release_checklist/check_chroma_subsampling.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python3 +"""Testing NV12 image encoding.""" + +from __future__ import annotations + +import os +from argparse import Namespace +from typing import Any +from uuid import uuid4 + +import cv2 +import numpy as np +import rerun as rr +import rerun.blueprint as rrb + +README = """\ +# Chroma subsampling + +All images should look roughly the same except for some chroma artifacts +and slight color differences due to different color primaries. + +Naturally, Y8 formats are greyscale. +""" + + +def bgra2y_u_v24(bgra: Any, full_range: bool) -> np.ndarray: + if full_range: + yvu = cv2.cvtColor(bgra, cv2.COLOR_BGR2YCrCb) + y, v, u = cv2.split(yvu) + else: + yuv = cv2.cvtColor(bgra, cv2.COLOR_BGR2YUV) + y, u, v = cv2.split(yuv) + y = np.array(y).flatten() + u = np.array(u).flatten() + v = np.array(v).flatten() + yuv24 = np.concatenate((y, u, v)) + return yuv24.astype(np.uint8) + + +def bgra2y_u_v16(bgra: Any, full_range: bool) -> np.ndarray: + if full_range: + yvu = cv2.cvtColor(bgra, cv2.COLOR_BGR2YCrCb) + y, v, u = cv2.split(yvu) + else: + yuv = cv2.cvtColor(bgra, cv2.COLOR_BGR2YUV) + y, u, v = cv2.split(yuv) + y = np.array(y).flatten() + u = np.array(cv2.resize(u, (u.shape[1] // 2, u.shape[0]))).flatten() + v = np.array(cv2.resize(v, (v.shape[1] // 2, v.shape[0]))).flatten() + yuv16 = np.concatenate((y, u, v)) + return yuv16.astype(np.uint8) + + +def bgra2y_u_v12(bgra: Any, full_range: bool) -> np.ndarray: + if full_range: + yvu = cv2.cvtColor(bgra, cv2.COLOR_BGR2YCrCb) + y, v, u = cv2.split(yvu) + else: + yuv = cv2.cvtColor(bgra, cv2.COLOR_BGR2YUV) + y, u, v = cv2.split(yuv) + y = np.array(y).flatten() + u = np.array(cv2.resize(u, (u.shape[1] // 2, u.shape[0] // 2))).flatten() + v = np.array(cv2.resize(v, (v.shape[1] // 2, v.shape[0] // 2))).flatten() + yuv12 = np.concatenate((y, u, v)) + return yuv12.astype(np.uint8) + + +def bgra2y8(bgra: Any, full_range: bool) -> np.ndarray: + if full_range: + yvu = cv2.cvtColor(bgra, cv2.COLOR_BGR2YCrCb) + y, _v, _u = cv2.split(yvu) + else: + yuv = cv2.cvtColor(bgra, cv2.COLOR_BGR2YUV) + y, _u, _v = cv2.split(yuv) + return y.astype(np.uint8) + + +def bgra2nv12(bgra: Any) -> np.ndarray: + yuv = cv2.cvtColor(bgra, cv2.COLOR_BGRA2YUV_I420) + uv_row_cnt = yuv.shape[0] // 3 + uv_plane = np.transpose(yuv[uv_row_cnt * 2 :].reshape(2, -1), [1, 0]) + yuv[uv_row_cnt * 2 :] = uv_plane.reshape(uv_row_cnt, -1) + return yuv + + +def bgra2yuy2(bgra: Any) -> np.ndarray: + yuv = cv2.cvtColor(bgra, cv2.COLOR_BGRA2YUV_YUY2) + (y, uv) = cv2.split(yuv) + + yuy2 = np.empty((y.shape[0], y.shape[1] * 2), dtype=y.dtype) + yuy2[:, 0::2] = y + yuy2[:, 1::4] = uv[:, ::2] + yuy2[:, 3::4] = uv[:, 1::2] + + return yuy2 + + +def log_readme() -> None: + rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True) + + +def blueprint() -> rrb.BlueprintLike: + return rrb.Grid( + rrb.TextDocumentView(origin="readme"), + rrb.Spatial2DView(origin="img_reference", name="Reference RGB"), + rrb.Spatial2DView(origin="img_V_U_V24_limited_range", name="Y_U_V24_limited_range"), + rrb.Spatial2DView(origin="img_V_U_V24_full_range", name="Y_U_V24_full_range"), + rrb.Spatial2DView(origin="img_V_U_V16_limited_range", name="Y_U_V16_limited_range"), + rrb.Spatial2DView(origin="img_V_U_V16_full_range", name="Y_U_V16_full_range"), + rrb.Spatial2DView(origin="img_V_U_V12_limited_range", name="Y_U_V12_limited_range"), + rrb.Spatial2DView(origin="img_V_U_V12_full_range", name="Y_U_V12_full_range"), + rrb.Spatial2DView(origin="img_y8_limited_range", name="Y8_limited_range"), + rrb.Spatial2DView(origin="img_y8_full_range", name="Y8_full_range"), + rrb.Spatial2DView(origin="img_nv12", name="NV12"), + rrb.Spatial2DView(origin="img_yuy2", name="YUY2"), + ) + + +def log_data() -> None: + # Make sure you use a colorful image! + dir_path = os.path.dirname(os.path.realpath(__file__)) + img_path = f"{dir_path}/../../../crates/viewer/re_ui/data/logo_dark_mode.png" + img_bgra = cv2.imread(img_path, cv2.IMREAD_UNCHANGED) + + img_rgb = cv2.cvtColor(img_bgra, cv2.COLOR_BGRA2RGB) + rr.log("img_reference", rr.Image(img_rgb, "rgb")) + + rr.log( + "img_V_U_V24_limited_range", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.Y_U_V24_LimitedRange, + bytes=bgra2y_u_v24(img_bgra, False).tobytes(), + ), + ) + rr.log( + "img_V_U_V16_limited_range", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.Y_U_V16_LimitedRange, + bytes=bgra2y_u_v16(img_bgra, False).tobytes(), + ), + ) + rr.log( + "img_V_U_V12_limited_range", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.Y_U_V12_LimitedRange, + bytes=bgra2y_u_v12(img_bgra, False).tobytes(), + ), + ) + rr.log( + "img_y8_limited_range", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.Y8_LimitedRange, + bytes=bgra2y8(img_bgra, False).tobytes(), + ), + ) + + rr.log( + "img_V_U_V24_full_range", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.Y_U_V24_FullRange, + bytes=bgra2y_u_v24(img_bgra, True).tobytes(), + ), + ) + rr.log( + "img_V_U_V16_full_range", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.Y_U_V16_FullRange, + bytes=bgra2y_u_v16(img_bgra, True).tobytes(), + ), + ) + rr.log( + "img_V_U_V12_full_range", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.Y_U_V12_FullRange, + bytes=bgra2y_u_v12(img_bgra, True).tobytes(), + ), + ) + rr.log( + "img_y8_full_range", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.Y8_FullRange, + bytes=bgra2y8(img_bgra, True).tobytes(), + ), + ) + + rr.log( + "img_nv12", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.NV12, + bytes=bgra2nv12(img_bgra).tobytes(), + ), + ) + rr.log( + "img_yuy2", + rr.Image( + width=img_bgra.shape[1], + height=img_bgra.shape[0], + pixel_format=rr.PixelFormat.YUY2, + bytes=bgra2yuy2(img_bgra).tobytes(), + ), + ) + + +def run(args: Namespace) -> None: + rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4(), default_blueprint=blueprint()) + + log_readme() + log_data() + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Interactive release checklist") + rr.script_add_args(parser) + args = parser.parse_args() + run(args) From bb58101f690516c58b43bf10467b6eb7f0b5363c Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Thu, 10 Oct 2024 18:25:41 +0200 Subject: [PATCH 04/33] Dataframe v2: "constant-time" pagination (#7665) This implements support for "constant-time" pagination. Obviously it's not constant-time, but it scales in a sane fashion. This PR is still _not_ about general performance optimizations. It is the last step before those can start though. * Fixes #7657 * DNM: requires #7652 --- Cargo.lock | 1 - crates/store/re_dataframe/Cargo.toml | 1 - crates/store/re_dataframe/src/query.rs | 378 ++++++++++++++++-- .../src/dataframe_ui.rs | 4 +- 4 files changed, 338 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3949173b595c..cafc4d1da18f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5131,7 +5131,6 @@ dependencies = [ name = "re_dataframe" version = "0.19.0-alpha.1+dev" dependencies = [ - "ahash", "anyhow", "itertools 0.13.0", "nohash-hasher", diff --git a/crates/store/re_dataframe/Cargo.toml b/crates/store/re_dataframe/Cargo.toml index 0b67d4b0e9b9..144168d505a1 100644 --- a/crates/store/re_dataframe/Cargo.toml +++ b/crates/store/re_dataframe/Cargo.toml @@ -34,7 +34,6 @@ re_tracing.workspace = true re_types_core.workspace = true # External dependencies: -ahash.workspace = true anyhow.workspace = true arrow2.workspace = true itertools.workspace = true diff --git a/crates/store/re_dataframe/src/query.rs b/crates/store/re_dataframe/src/query.rs index 1b310539443f..2abf8c7227ca 100644 --- a/crates/store/re_dataframe/src/query.rs +++ b/crates/store/re_dataframe/src/query.rs @@ -1,9 +1,11 @@ -use std::sync::{ - atomic::{AtomicU64, Ordering}, - OnceLock, +use std::{ + collections::BTreeSet, + sync::{ + atomic::{AtomicU64, Ordering}, + OnceLock, + }, }; -use ahash::HashSet; use arrow2::{ array::{ Array as ArrowArray, BooleanArray as ArrowBooleanArray, @@ -41,7 +43,7 @@ use crate::{QueryEngine, RecordBatch}; // * [x] latestat sparse-filling // * [x] sampling support // * [x] clears -// * [ ] pagination (fast) +// * [x] pagination (fast) // * [ ] overlaps (less dumb) // * [ ] selector-based `filtered_index` // * [ ] configurable cache bypass @@ -125,7 +127,18 @@ struct QueryHandleState { /// /// This represents the number of rows that the caller has iterated on: it is completely /// unrelated to the cursors used to track the current position in each individual chunk. + /// + /// The corresponding index value can be obtained using `unique_index_values[cur_row]`. + /// + /// `unique_index_values[cur_row]`: [`QueryHandleState::unique_index_values`] cur_row: AtomicU64, + + /// All unique index values that can possibly be returned by this query. + /// + /// Guaranteed ascendingly sorted and deduped. + /// + /// See also [`QueryHandleState::cur_row`]. + unique_index_values: Vec, } impl<'a> QueryHandle<'a> { @@ -266,6 +279,47 @@ impl QueryHandle<'_> { } } + // 6. Collect all unique index values. + // + // Used to achieve ~O(log(n)) pagination. + let unique_index_values = + if let Some(using_index_values_stack) = using_index_values_stack.as_ref() { + let mut all_unique_index_values = using_index_values_stack.clone(); + all_unique_index_values.sort(); + all_unique_index_values + } else { + re_tracing::profile_scope!("index_values"); + + let mut view_chunks = view_chunks.iter(); + let view_chunks = if let Some(view_pov_chunks_idx) = view_pov_chunks_idx { + Either::Left(view_chunks.nth(view_pov_chunks_idx).into_iter()) + } else { + Either::Right(view_chunks) + }; + + let mut all_unique_index_values: BTreeSet = view_chunks + .flat_map(|chunks| { + chunks.iter().filter_map(|(_cursor, chunk)| { + if chunk.is_static() { + Some(Either::Left(std::iter::once(TimeInt::STATIC))) + } else { + chunk + .timelines() + .get(&self.query.filtered_index) + .map(|time_column| Either::Right(time_column.times())) + } + }) + }) + .flatten() + .collect(); + + if let Some(filtered_index_values) = self.query.filtered_index_values.as_ref() { + all_unique_index_values.retain(|time| filtered_index_values.contains(time)); + } + + all_unique_index_values.into_iter().collect_vec() + }; + QueryHandleState { view_contents, selected_contents, @@ -274,6 +328,7 @@ impl QueryHandle<'_> { view_pov_chunks_idx, using_index_values_stack: Mutex::new(using_index_values_stack), cur_row: AtomicU64::new(0), + unique_index_values, } } @@ -579,45 +634,108 @@ impl QueryHandle<'_> { &self.init().arrow_schema } - /// How many rows of data will be returned? + /// Advance all internal cursors so that the next row yielded will correspond to `row_idx`. /// - /// The number of rows depends and only depends on the _view contents_. - /// The _selected contents_ has no influence on this value. - // - // TODO(cmc): implement this properly, cache the result, etc. - pub fn num_rows(&self) -> u64 { + /// Does nothing if `row_idx` is out of bounds. + /// + /// ## Concurrency + /// + /// Cursors are implemented using atomic variables, which means calling any of the `seek_*` + /// while iteration is concurrently ongoing is memory-safe but logically undefined racy + /// behavior. Be careful. + /// + /// ## Performance + /// + /// This requires going through every chunk once, and for each chunk running a binary search if + /// the chunk's time range contains the `index_value`. + /// + /// I.e.: it's pretty cheap already. + #[inline] + pub fn seek_to_row(&self, row_idx: usize) { + let Some(index_value) = self.init().unique_index_values.get(row_idx) else { + return; + }; + + self.seek_to_index_value(*index_value); + } + + /// Advance all internal cursors so that the next row yielded will correspond to `index_value`. + /// + /// If `index_value` isn't present in the dataset, this seeks to the first index value + /// available past that point, if any. + /// + /// ## Concurrency + /// + /// Cursors are implemented using atomic variables, which means calling any of the `seek_*` + /// while iteration is concurrently ongoing is memory-safe but logically undefined racy + /// behavior. Be careful. + /// + /// ## Performance + /// + /// This requires going through every chunk once, and for each chunk running a binary search if + /// the chunk's time range contains the `index_value`. + /// + /// I.e.: it's pretty cheap already. + pub fn seek_to_index_value(&self, index_value: IndexValue) { re_tracing::profile_function!(); let state = self.init(); - let mut view_chunks = state.view_chunks.iter(); - let view_chunks = if let Some(view_pov_chunks_idx) = state.view_pov_chunks_idx { - Either::Left(view_chunks.nth(view_pov_chunks_idx).into_iter()) - } else { - Either::Right(view_chunks) - }; + // NOTE: If there are explicit samples specified, then we need to make sure to properly reset + // them each time an arbitrary seek happens. + let mut using_index_values_stack = state.using_index_values_stack.lock(); + if using_index_values_stack.is_some() { + let mut index_values = state + .unique_index_values + .iter() + .filter(|&&v| v >= index_value) + .copied() + .collect_vec(); + index_values.reverse(); + *using_index_values_stack = Some(index_values); + } - let mut all_unique_timestamps: HashSet = view_chunks - .flat_map(|chunks| { - chunks.iter().filter_map(|(_cursor, chunk)| { - if chunk.is_static() { - Some(Either::Left(std::iter::once(TimeInt::STATIC))) - } else { - chunk - .timelines() - .get(&self.query.filtered_index) - .map(|time_column| Either::Right(time_column.times())) - } - }) - }) - .flatten() - .collect(); + if index_value.is_static() { + for chunks in &state.view_chunks { + for (cursor, _chunk) in chunks { + cursor.store(0, Ordering::Relaxed); + } + } + return; + } + + for chunks in &state.view_chunks { + for (cursor, chunk) in chunks { + // NOTE: The chunk has been densified already: its global time range is the same as + // the time range for the specific component of interest. + let Some(time_column) = chunk.timelines().get(&self.query.filtered_index) else { + continue; + }; - if let Some(filtered_index_values) = self.query.filtered_index_values.as_ref() { - all_unique_timestamps.retain(|time| filtered_index_values.contains(time)); + let time_range = time_column.time_range(); + + let new_cursor = if index_value < time_range.min() { + 0 + } else if index_value > time_range.max() { + chunk.num_rows() as u64 /* yes, one past the end -- not a mistake */ + } else { + time_column + .times_raw() + .partition_point(|&time| time < index_value.as_i64()) + as u64 + }; + + cursor.store(new_cursor, Ordering::Relaxed); + } } + } - let num_rows = all_unique_timestamps.len() as _; + /// How many rows of data will be returned? + /// + /// The number of rows depends and only depends on the _view contents_. + /// The _selected contents_ has no influence on this value. + pub fn num_rows(&self) -> u64 { + let num_rows = self.init().unique_index_values.len() as _; if cfg!(debug_assertions) { let expected_num_rows = @@ -646,16 +764,13 @@ impl QueryHandle<'_> { /// /// ## Pagination /// - /// This does not offer any kind of native pagination yet. - /// - /// To emulate pagination from user-space, use the `Iterator` API: + /// Use [`Self::seek_to_row`] and [`Self::seek_to_index_value`]: /// ```ignore - /// for row in query_handle.into_iter().skip(offset).take(len) { + /// query_handle.seek_to_row(42); + /// for row in query_handle.into_iter().take(len) { /// // … /// } /// ``` - // - // TODO(cmc): better/actual pagination pub fn next_row(&self) -> Option>> { re_tracing::profile_function!(); @@ -1078,12 +1193,24 @@ impl QueryHandle<'_> { } impl<'a> QueryHandle<'a> { + /// Returns an iterator backed by [`Self::next_row`]. + #[allow(clippy::should_implement_trait)] // we need an anonymous closure, this won't work + pub fn iter(&'a self) -> impl Iterator>> + 'a { + std::iter::from_fn(move || self.next_row()) + } + /// Returns an iterator backed by [`Self::next_row`]. #[allow(clippy::should_implement_trait)] // we need an anonymous closure, this won't work pub fn into_iter(self) -> impl Iterator>> + 'a { std::iter::from_fn(move || self.next_row()) } + /// Returns an iterator backed by [`Self::next_row_batch`]. + #[allow(clippy::should_implement_trait)] // we need an anonymous closure, this won't work + pub fn batch_iter(&'a self) -> impl Iterator + 'a { + std::iter::from_fn(move || self.next_row_batch()) + } + /// Returns an iterator backed by [`Self::next_row_batch`]. #[allow(clippy::should_implement_trait)] // we need an anonymous closure, this won't work pub fn into_batch_iter(self) -> impl Iterator + 'a { @@ -1133,7 +1260,7 @@ mod tests { // * [x] num_rows // * [x] clears // * [ ] timelines returned with selection=none - // * [ ] pagination + // * [x] pagination // TODO(cmc): At some point I'd like to stress multi-entity queries too, but that feels less // urgent considering how things are implemented (each entity lives in its own index, so it's @@ -1974,6 +2101,173 @@ mod tests { Ok(()) } + #[test] + fn pagination() -> anyhow::Result<()> { + re_log::setup_logging(); + + let store = create_nasty_store()?; + eprintln!("{store}"); + let query_cache = QueryCache::new(&store); + let query_engine = QueryEngine { + store: &store, + cache: &query_cache, + }; + + let timeline = Timeline::new_sequence("frame_nr"); + let entity_path = EntityPath::from("this/that"); + + // basic + { + let query = QueryExpression::new(timeline); + eprintln!("{query:#?}:"); + + let query_handle = query_engine.query(query.clone()); + assert_eq!( + query_engine.query(query.clone()).into_iter().count() as u64, + query_handle.num_rows(), + ); + + let expected_rows = query_handle.batch_iter().collect_vec(); + + for _ in 0..3 { + for i in 0..expected_rows.len() { + query_handle.seek_to_row(i); + + let expected = concatenate_record_batches( + query_handle.schema().clone(), + &expected_rows.iter().skip(i).take(3).cloned().collect_vec(), + ); + let got = concatenate_record_batches( + query_handle.schema().clone(), + &query_handle.batch_iter().take(3).collect_vec(), + ); + + let expected = format!("{:#?}", expected.data.iter().collect_vec()); + let got = format!("{:#?}", got.data.iter().collect_vec()); + + similar_asserts::assert_eq!(expected, got); + } + } + } + + // with pov + { + let mut query = QueryExpression::new(timeline); + query.filtered_point_of_view = Some(ComponentColumnSelector { + entity_path: entity_path.clone(), + component: MyPoint::name(), + join_encoding: Default::default(), + }); + eprintln!("{query:#?}:"); + + let query_handle = query_engine.query(query.clone()); + assert_eq!( + query_engine.query(query.clone()).into_iter().count() as u64, + query_handle.num_rows(), + ); + + let expected_rows = query_handle.batch_iter().collect_vec(); + + for _ in 0..3 { + for i in 0..expected_rows.len() { + query_handle.seek_to_row(i); + + let expected = concatenate_record_batches( + query_handle.schema().clone(), + &expected_rows.iter().skip(i).take(3).cloned().collect_vec(), + ); + let got = concatenate_record_batches( + query_handle.schema().clone(), + &query_handle.batch_iter().take(3).collect_vec(), + ); + + let expected = format!("{:#?}", expected.data.iter().collect_vec()); + let got = format!("{:#?}", got.data.iter().collect_vec()); + + similar_asserts::assert_eq!(expected, got); + } + } + } + + // with sampling + { + let mut query = QueryExpression::new(timeline); + query.using_index_values = Some( + [0, 15, 30, 30, 45, 60, 75, 90] + .into_iter() + .map(TimeInt::new_temporal) + .chain(std::iter::once(TimeInt::STATIC)) + .collect(), + ); + eprintln!("{query:#?}:"); + + let query_handle = query_engine.query(query.clone()); + assert_eq!( + query_engine.query(query.clone()).into_iter().count() as u64, + query_handle.num_rows(), + ); + + let expected_rows = query_handle.batch_iter().collect_vec(); + + for _ in 0..3 { + for i in 0..expected_rows.len() { + query_handle.seek_to_row(i); + + let expected = concatenate_record_batches( + query_handle.schema().clone(), + &expected_rows.iter().skip(i).take(3).cloned().collect_vec(), + ); + let got = concatenate_record_batches( + query_handle.schema().clone(), + &query_handle.batch_iter().take(3).collect_vec(), + ); + + let expected = format!("{:#?}", expected.data.iter().collect_vec()); + let got = format!("{:#?}", got.data.iter().collect_vec()); + + similar_asserts::assert_eq!(expected, got); + } + } + } + + // with sparse-fill + { + let mut query = QueryExpression::new(timeline); + query.sparse_fill_strategy = SparseFillStrategy::LatestAtGlobal; + eprintln!("{query:#?}:"); + + let query_handle = query_engine.query(query.clone()); + assert_eq!( + query_engine.query(query.clone()).into_iter().count() as u64, + query_handle.num_rows(), + ); + + let expected_rows = query_handle.batch_iter().collect_vec(); + + for _ in 0..3 { + for i in 0..expected_rows.len() { + query_handle.seek_to_row(i); + + let expected = concatenate_record_batches( + query_handle.schema().clone(), + &expected_rows.iter().skip(i).take(3).cloned().collect_vec(), + ); + let got = concatenate_record_batches( + query_handle.schema().clone(), + &query_handle.batch_iter().take(3).collect_vec(), + ); + + let expected = format!("{:#?}", expected.data.iter().collect_vec()); + let got = format!("{:#?}", got.data.iter().collect_vec()); + + similar_asserts::assert_eq!(expected, got); + } + } + } + + Ok(()) + } + /// Returns a very nasty [`ChunkStore`] with all kinds of partial updates, chunk overlaps, /// repeated timestamps, duplicated chunks, partial multi-timelines, flat and recursive clears, etc. fn create_nasty_store() -> anyhow::Result { diff --git a/crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs b/crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs index ab151588835b..0fb0cba0ff94 100644 --- a/crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs +++ b/crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs @@ -202,9 +202,9 @@ impl<'a> egui_table::TableDelegate for DataframeTableDelegate<'a> { let timeline = self.query_handle.query().filtered_index; - //TODO(ab, cmc): we probably need a better way to run a paginated query. + self.query_handle + .seek_to_row(info.visible_rows.start as usize); let data = std::iter::from_fn(|| self.query_handle.next_row()) - .skip(info.visible_rows.start as usize) .take((info.visible_rows.end - info.visible_rows.start) as usize) .collect(); From b248c88565ee8a99acf5389c197aa39ebcbc1896 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 11 Oct 2024 09:31:06 +0200 Subject: [PATCH 05/33] Show what video frame is shown when hovering video in selection panel (#7685) ### What * Part of https://github.com/rerun-io/rerun/issues/7647 Screenshot 2024-10-11 at 09 12 23 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7685?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7685?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7685) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/utils/re_format/src/time.rs | 7 +++---- crates/viewer/re_data_ui/src/blob.rs | 18 ++++++++++++++++++ .../re_renderer/src/video/decoder/mod.rs | 1 + crates/viewer/re_renderer/src/video/mod.rs | 5 ++++- .../src/visualizers/videos.rs | 1 + 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/crates/utils/re_format/src/time.rs b/crates/utils/re_format/src/time.rs index 5538e4080e44..52d99bcb0461 100644 --- a/crates/utils/re_format/src/time.rs +++ b/crates/utils/re_format/src/time.rs @@ -27,13 +27,12 @@ pub fn format_timestamp_seconds(timestamp_seconds: f64) -> String { let n = timestamp_seconds as i32; let hours = n / (60 * 60); let mins = (n / 60) % 60; - let secs_int = n % 60; - let secs_hundredth = (timestamp_seconds.fract() * 100.0) as u32; + let secs = (n % 60) as f64 + timestamp_seconds.fract(); if hours > 0 { - format!("{hours:02}:{mins:02}:{secs_int:02}.{secs_hundredth:02}") + format!("{hours:02}:{mins:02}:{secs:02.02}") } else { - format!("{mins:02}:{secs_int:02}.{secs_hundredth:02}") + format!("{mins:02}:{secs:02.02}") } // Not showing the minutes at all makes it too unclear what format this timestamp is in. // So let's not further strip this down. diff --git a/crates/viewer/re_data_ui/src/blob.rs b/crates/viewer/re_data_ui/src/blob.rs index 805513a7c5c2..6c43b3922dec 100644 --- a/crates/viewer/re_data_ui/src/blob.rs +++ b/crates/viewer/re_data_ui/src/blob.rs @@ -251,6 +251,7 @@ fn show_video_blob_info( match video.frame_at(render_ctx, decode_stream_id, timestamp_in_seconds) { Ok(VideoFrameTexture { texture, + time_range, is_pending, show_spinner, }) => { @@ -274,6 +275,23 @@ fn show_video_blob_info( ); egui::Spinner::new().paint_at(ui, smaller_rect); } + + response.on_hover_ui(|ui| { + // Prevent `Area` auto-sizing from shrinking tooltips with dynamic content. + // See https://github.com/emilk/egui/issues/5167 + ui.set_max_width(ui.spacing().tooltip_width); + + let timescale = video.data().timescale; + ui.label(format!( + "Frame at {} - {}", + re_format::format_timestamp_seconds( + time_range.start.into_secs(timescale), + ), + re_format::format_timestamp_seconds( + time_range.end.into_secs(timescale), + ), + )); + }); } Err(err) => { diff --git a/crates/viewer/re_renderer/src/video/decoder/mod.rs b/crates/viewer/re_renderer/src/video/decoder/mod.rs index 97ecd40dfcbd..cf5add19a795 100644 --- a/crates/viewer/re_renderer/src/video/decoder/mod.rs +++ b/crates/viewer/re_renderer/src/video/decoder/mod.rs @@ -233,6 +233,7 @@ impl VideoDecoder { Ok(VideoFrameTexture { texture: self.video_texture.texture.clone(), + time_range: self.video_texture.time_range.clone(), is_pending, show_spinner, }) diff --git a/crates/viewer/re_renderer/src/video/mod.rs b/crates/viewer/re_renderer/src/video/mod.rs index 517c6ecc08c2..659fed6131e5 100644 --- a/crates/viewer/re_renderer/src/video/mod.rs +++ b/crates/viewer/re_renderer/src/video/mod.rs @@ -1,6 +1,6 @@ mod decoder; -use std::{collections::hash_map::Entry, sync::Arc}; +use std::{collections::hash_map::Entry, ops::Range, sync::Arc}; use ahash::HashMap; use parking_lot::Mutex; @@ -69,6 +69,9 @@ pub struct VideoFrameTexture { /// The texture to show. pub texture: GpuTexture2D, + /// What part of the video this video frame covers. + pub time_range: Range, + /// If true, the texture is outdated. Keep polling for a fresh one. pub is_pending: bool, diff --git a/crates/viewer/re_space_view_spatial/src/visualizers/videos.rs b/crates/viewer/re_space_view_spatial/src/visualizers/videos.rs index b7ce6e25c9b8..12ece086966c 100644 --- a/crates/viewer/re_space_view_spatial/src/visualizers/videos.rs +++ b/crates/viewer/re_space_view_spatial/src/visualizers/videos.rs @@ -197,6 +197,7 @@ impl VideoFrameReferenceVisualizer { match video.frame_at(render_ctx, decode_stream_id, video_timestamp.as_seconds()) { Ok(VideoFrameTexture { texture, + time_range: _, // TODO(emilk): maybe add to `PickableTexturedRect` and `PickingHitType::TexturedRect` so we can show on hover? is_pending, show_spinner, }) => { From 62139dfcf657ec32aae1d4a33ee5ff8265457062 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 11 Oct 2024 11:30:18 +0200 Subject: [PATCH 06/33] Remove experimental flags from video api types (#7688) ### What We still had those in, but we're getting close for shipping those as non-experimental! :) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7688?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7688?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7688) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../definitions/rerun/archetypes/asset_video.fbs | 3 +-- .../rerun/archetypes/video_frame_reference.fbs | 3 +-- .../definitions/rerun/components/video_timestamp.fbs | 1 - .../definitions/rerun/datatypes/video_timestamp.fbs | 1 - crates/store/re_types/src/archetypes/asset_video.rs | 2 -- .../re_types/src/archetypes/video_frame_reference.rs | 2 -- .../store/re_types/src/components/video_timestamp.rs | 2 -- .../store/re_types/src/datatypes/video_timestamp.rs | 2 -- crates/viewer/re_viewer/src/reflection/mod.rs | 11 +++++------ .../content/reference/types/archetypes/asset_video.md | 3 --- .../types/archetypes/video_frame_reference.md | 3 --- .../reference/types/components/video_timestamp.md | 3 --- .../reference/types/datatypes/video_timestamp.md | 3 --- rerun_cpp/src/rerun/archetypes/asset_video.hpp | 2 -- .../src/rerun/archetypes/video_frame_reference.hpp | 2 -- rerun_cpp/src/rerun/components/video_timestamp.hpp | 2 -- rerun_cpp/src/rerun/datatypes/video_timestamp.hpp | 2 -- rerun_py/rerun_sdk/rerun/archetypes/asset_video.py | 2 -- .../rerun/archetypes/video_frame_reference.py | 2 -- .../rerun_sdk/rerun/components/video_timestamp.py | 6 +----- rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py | 2 -- 21 files changed, 8 insertions(+), 51 deletions(-) diff --git a/crates/store/re_types/definitions/rerun/archetypes/asset_video.fbs b/crates/store/re_types/definitions/rerun/archetypes/asset_video.fbs index c6270c3c1d17..0190d6f0eb33 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/asset_video.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/asset_video.fbs @@ -12,8 +12,7 @@ namespace rerun.archetypes; /// \example archetypes/video_auto_frames title="Video with automatically determined frames" image="https://static.rerun.io/video_manual_frames/320a44e1e06b8b3a3161ecbbeae3e04d1ccb9589/1200w.png" /// \example archetypes/video_manual_frames title="Demonstrates manual use of video frame references" image="https://static.rerun.io/video_manual_frames/9f41c00f84a98cc3f26875fba7c1d2fa2bad7151/1200w.png" table AssetVideo ( - "attr.docs.unreleased", - "attr.rerun.experimental" + "attr.docs.unreleased" ) { // --- Required --- diff --git a/crates/store/re_types/definitions/rerun/archetypes/video_frame_reference.fbs b/crates/store/re_types/definitions/rerun/archetypes/video_frame_reference.fbs index cf66cc9355b3..481d31c92a0f 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/video_frame_reference.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/video_frame_reference.fbs @@ -10,8 +10,7 @@ namespace rerun.archetypes; /// \example archetypes/video_auto_frames title="Video with automatically determined frames" image="https://static.rerun.io/video_manual_frames/320a44e1e06b8b3a3161ecbbeae3e04d1ccb9589/1200w.png" /// \example archetypes/video_manual_frames title="Demonstrates manual use of video frame references" image="https://static.rerun.io/video_manual_frames/9f41c00f84a98cc3f26875fba7c1d2fa2bad7151/1200w.png" table VideoFrameReference ( - "attr.docs.unreleased", - "attr.rerun.experimental" + "attr.docs.unreleased" ){ // --- Required --- diff --git a/crates/store/re_types/definitions/rerun/components/video_timestamp.fbs b/crates/store/re_types/definitions/rerun/components/video_timestamp.fbs index 3a2b597e8b32..90353a494a65 100644 --- a/crates/store/re_types/definitions/rerun/components/video_timestamp.fbs +++ b/crates/store/re_types/definitions/rerun/components/video_timestamp.fbs @@ -4,7 +4,6 @@ namespace rerun.components; /// Timestamp inside a [archetypes.AssetVideo]. struct VideoTimestamp ( "attr.docs.unreleased", - "attr.rerun.experimental", "attr.arrow.transparent", "attr.rust.derive": "Copy, PartialEq, Eq, Default", "attr.rust.repr": "transparent" diff --git a/crates/store/re_types/definitions/rerun/datatypes/video_timestamp.fbs b/crates/store/re_types/definitions/rerun/datatypes/video_timestamp.fbs index dd767702d244..51bda40d35a3 100644 --- a/crates/store/re_types/definitions/rerun/datatypes/video_timestamp.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes/video_timestamp.fbs @@ -6,7 +6,6 @@ namespace rerun.datatypes; /// Presentation timestamps are typically measured as time since video start. struct VideoTimestamp ( "attr.arrow.transparent", - "attr.rerun.experimental", "attr.docs.unreleased", "attr.python.aliases": "int", "attr.rust.derive": "Default, Copy, PartialEq, Eq, PartialOrd, Ord", diff --git a/crates/store/re_types/src/archetypes/asset_video.rs b/crates/store/re_types/src/archetypes/asset_video.rs index 609656a87b4d..d0c64526b632 100644 --- a/crates/store/re_types/src/archetypes/asset_video.rs +++ b/crates/store/re_types/src/archetypes/asset_video.rs @@ -27,8 +27,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// In order to display a video, you also need to log a [`archetypes::VideoFrameReference`][crate::archetypes::VideoFrameReference] for each frame. /// -/// ⚠️ **This type is experimental and may be removed in future versions** -/// /// ## Examples /// /// ### Video with automatically determined frames diff --git a/crates/store/re_types/src/archetypes/video_frame_reference.rs b/crates/store/re_types/src/archetypes/video_frame_reference.rs index c5f434fd6bc5..42143f2935f6 100644 --- a/crates/store/re_types/src/archetypes/video_frame_reference.rs +++ b/crates/store/re_types/src/archetypes/video_frame_reference.rs @@ -25,8 +25,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// See for details of what is and isn't supported. /// -/// ⚠️ **This type is experimental and may be removed in future versions** -/// /// ## Examples /// /// ### Video with automatically determined frames diff --git a/crates/store/re_types/src/components/video_timestamp.rs b/crates/store/re_types/src/components/video_timestamp.rs index db077fcf40dd..704905e80090 100644 --- a/crates/store/re_types/src/components/video_timestamp.rs +++ b/crates/store/re_types/src/components/video_timestamp.rs @@ -19,8 +19,6 @@ use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: Timestamp inside a [`archetypes::AssetVideo`][crate::archetypes::AssetVideo]. -/// -/// ⚠️ **This type is experimental and may be removed in future versions** #[derive(Clone, Debug, Copy, PartialEq, Eq, Default)] #[repr(transparent)] pub struct VideoTimestamp(pub crate::datatypes::VideoTimestamp); diff --git a/crates/store/re_types/src/datatypes/video_timestamp.rs b/crates/store/re_types/src/datatypes/video_timestamp.rs index f279f96cf143..de4a7a383bd5 100644 --- a/crates/store/re_types/src/datatypes/video_timestamp.rs +++ b/crates/store/re_types/src/datatypes/video_timestamp.rs @@ -22,8 +22,6 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// Specified in nanoseconds. /// Presentation timestamps are typically measured as time since video start. -/// -/// ⚠️ **This type is experimental and may be removed in future versions** #[derive(Clone, Debug, Default, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct VideoTimestamp( /// Presentation timestamp value in nanoseconds. diff --git a/crates/viewer/re_viewer/src/reflection/mod.rs b/crates/viewer/re_viewer/src/reflection/mod.rs index 92e4eb2f0358..24d6a1935d60 100644 --- a/crates/viewer/re_viewer/src/reflection/mod.rs +++ b/crates/viewer/re_viewer/src/reflection/mod.rs @@ -688,7 +688,7 @@ fn generate_component_reflection() -> Result::name(), ComponentReflection { - docstring_md: "Timestamp inside a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video?speculative-link).\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", + docstring_md: "Timestamp inside a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video?speculative-link).", placeholder: Some(VideoTimestamp::default().to_arrow()?), }, ), @@ -818,12 +818,11 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { display_name: "Asset video", fields: vec![ ArchetypeFieldReflection { component_name : "rerun.components.Blob" - .into(), display_name : "Blob", docstring_md : - "The asset's bytes.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", + .into(), display_name : "Blob", docstring_md : "The asset's bytes.", is_required : true, }, ArchetypeFieldReflection { component_name : "rerun.components.MediaType".into(), display_name : "Media type", docstring_md : - "The Media Type of the asset.\n\nSupported values:\n* `video/mp4`\n\nIf omitted, the viewer will try to guess from the data blob.\nIf it cannot guess, it won't be able to render the asset.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", + "The Media Type of the asset.\n\nSupported values:\n* `video/mp4`\n\nIf omitted, the viewer will try to guess from the data blob.\nIf it cannot guess, it won't be able to render the asset.", is_required : false, }, ], }, @@ -1482,11 +1481,11 @@ fn generate_archetype_reflection() -> ArchetypeReflectionMap { ArchetypeFieldReflection { component_name : "rerun.components.VideoTimestamp".into(), display_name : "Timestamp", docstring_md : - "References the closest video frame to this timestamp.\n\nNote that this uses the closest video frame instead of the latest at this timestamp\nin order to be more forgiving of rounding errors for inprecise timestamp types.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", + "References the closest video frame to this timestamp.\n\nNote that this uses the closest video frame instead of the latest at this timestamp\nin order to be more forgiving of rounding errors for inprecise timestamp types.", is_required : true, }, ArchetypeFieldReflection { component_name : "rerun.components.EntityPath".into(), display_name : "Video reference", docstring_md : - "Optional reference to an entity with a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video?speculative-link).\n\nIf none is specified, the video is assumed to be at the same entity.\nNote that blueprint overrides on the referenced video will be ignored regardless,\nas this is always interpreted as a reference to the data store.\n\nFor a series of video frame references, it is recommended to specify this path only once\nat the beginning of the series and then rely on latest-at query semantics to\nkeep the video reference active.\n\n⚠\u{fe0f} **This type is experimental and may be removed in future versions**", + "Optional reference to an entity with a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video?speculative-link).\n\nIf none is specified, the video is assumed to be at the same entity.\nNote that blueprint overrides on the referenced video will be ignored regardless,\nas this is always interpreted as a reference to the data store.\n\nFor a series of video frame references, it is recommended to specify this path only once\nat the beginning of the series and then rely on latest-at query semantics to\nkeep the video reference active.", is_required : false, }, ], }, diff --git a/docs/content/reference/types/archetypes/asset_video.md b/docs/content/reference/types/archetypes/asset_video.md index b7b7affe7509..34ffa59c7bf3 100644 --- a/docs/content/reference/types/archetypes/asset_video.md +++ b/docs/content/reference/types/archetypes/asset_video.md @@ -3,9 +3,6 @@ title: "AssetVideo" --- - -⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - A video binary. NOTE: Videos can only be viewed in the Rerun web viewer. diff --git a/docs/content/reference/types/archetypes/video_frame_reference.md b/docs/content/reference/types/archetypes/video_frame_reference.md index 359adbe6101e..311d6e6f7f2d 100644 --- a/docs/content/reference/types/archetypes/video_frame_reference.md +++ b/docs/content/reference/types/archetypes/video_frame_reference.md @@ -3,9 +3,6 @@ title: "VideoFrameReference" --- - -⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - References a single video frame. Used to display individual video frames from a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video?speculative-link). diff --git a/docs/content/reference/types/components/video_timestamp.md b/docs/content/reference/types/components/video_timestamp.md index 7c940f7a61d8..f056688b5ccf 100644 --- a/docs/content/reference/types/components/video_timestamp.md +++ b/docs/content/reference/types/components/video_timestamp.md @@ -3,9 +3,6 @@ title: "VideoTimestamp" --- - -⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - Timestamp inside a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video?speculative-link). ## Fields diff --git a/docs/content/reference/types/datatypes/video_timestamp.md b/docs/content/reference/types/datatypes/video_timestamp.md index 73f57cb31ed6..762f53246778 100644 --- a/docs/content/reference/types/datatypes/video_timestamp.md +++ b/docs/content/reference/types/datatypes/video_timestamp.md @@ -3,9 +3,6 @@ title: "VideoTimestamp" --- - -⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - Presentation timestamp within a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video?speculative-link). Specified in nanoseconds. diff --git a/rerun_cpp/src/rerun/archetypes/asset_video.hpp b/rerun_cpp/src/rerun/archetypes/asset_video.hpp index 630eb241b7f5..3d9dd80f1054 100644 --- a/rerun_cpp/src/rerun/archetypes/asset_video.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset_video.hpp @@ -115,8 +115,6 @@ namespace rerun::archetypes { /// // TODO(#5520): log blueprint once supported /// } /// ``` - /// - /// ⚠ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** struct AssetVideo { /// The asset's bytes. rerun::components::Blob blob; diff --git a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp index 180691b122ed..254279dde5ce 100644 --- a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp +++ b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp @@ -111,8 +111,6 @@ namespace rerun::archetypes { /// // TODO(#5520): log blueprint once supported /// } /// ``` - /// - /// ⚠ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** struct VideoFrameReference { /// References the closest video frame to this timestamp. /// diff --git a/rerun_cpp/src/rerun/components/video_timestamp.hpp b/rerun_cpp/src/rerun/components/video_timestamp.hpp index f91261d0ef1d..6e44eb838874 100644 --- a/rerun_cpp/src/rerun/components/video_timestamp.hpp +++ b/rerun_cpp/src/rerun/components/video_timestamp.hpp @@ -12,8 +12,6 @@ namespace rerun::components { /// **Component**: Timestamp inside a `archetypes::AssetVideo`. - /// - /// ⚠ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** struct VideoTimestamp { rerun::datatypes::VideoTimestamp timestamp; diff --git a/rerun_cpp/src/rerun/datatypes/video_timestamp.hpp b/rerun_cpp/src/rerun/datatypes/video_timestamp.hpp index 39908a6fb4a3..50256bd71153 100644 --- a/rerun_cpp/src/rerun/datatypes/video_timestamp.hpp +++ b/rerun_cpp/src/rerun/datatypes/video_timestamp.hpp @@ -24,8 +24,6 @@ namespace rerun::datatypes { /// /// Specified in nanoseconds. /// Presentation timestamps are typically measured as time since video start. - /// - /// ⚠ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** struct VideoTimestamp { /// Presentation timestamp value in nanoseconds. int64_t timestamp_ns; diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py index 730baab98d69..4709296b2a58 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py @@ -28,8 +28,6 @@ class AssetVideo(AssetVideoExt, Archetype): In order to display a video, you also need to log a [`archetypes.VideoFrameReference`][rerun.archetypes.VideoFrameReference] for each frame. - ⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - Examples -------- ### Video with automatically determined frames: diff --git a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py index 2a078d5f0991..5ae51042c52e 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py @@ -28,8 +28,6 @@ class VideoFrameReference(Archetype): See for details of what is and isn't supported. - ⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - Examples -------- ### Video with automatically determined frames: diff --git a/rerun_py/rerun_sdk/rerun/components/video_timestamp.py b/rerun_py/rerun_sdk/rerun/components/video_timestamp.py index 41fa33bcf3c0..5c17293627f0 100644 --- a/rerun_py/rerun_sdk/rerun/components/video_timestamp.py +++ b/rerun_py/rerun_sdk/rerun/components/video_timestamp.py @@ -16,11 +16,7 @@ class VideoTimestamp(VideoTimestampExt, datatypes.VideoTimestamp, ComponentMixin): - """ - **Component**: Timestamp inside a [`archetypes.AssetVideo`][rerun.archetypes.AssetVideo]. - - ⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** - """ + """**Component**: Timestamp inside a [`archetypes.AssetVideo`][rerun.archetypes.AssetVideo].""" _BATCH_TYPE = None # __init__ can be found in video_timestamp_ext.py diff --git a/rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py b/rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py index 3555a031a8da..74b3bc01ce42 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/video_timestamp.py @@ -33,8 +33,6 @@ class VideoTimestamp: Specified in nanoseconds. Presentation timestamps are typically measured as time since video start. - - ⚠️ **This is an experimental API! It is not fully supported, and is likely to change significantly in future versions.** """ def __init__(self: Any, timestamp_ns: VideoTimestampLike): From c06745f71bfec9fee0789a39b305ed7b2003c8ce Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 11 Oct 2024 13:32:26 +0200 Subject: [PATCH 07/33] Document that Rerun does not support left-handed coords (#7690) ### What * Closes https://github.com/rerun-io/rerun/issues/5033 * Screenshot 2024-10-11 at 11 27 56 Screenshot 2024-10-11 at 11 25 48 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7690?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7690?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7690) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- .../rerun/archetypes/view_coordinates.fbs | 4 +- .../rerun/components/view_coordinates.fbs | 4 +- .../rerun/datatypes/view_coordinates.fbs | 4 +- .../src/archetypes/view_coordinates.rs | 4 +- .../src/archetypes/view_coordinates_ext.rs | 120 +++++++++++++----- .../src/components/view_coordinates.rs | 4 +- .../src/components/view_coordinates_ext.rs | 120 +++++++++++++----- .../src/datatypes/view_coordinates.rs | 4 +- crates/viewer/re_viewer/src/reflection/mod.rs | 2 +- .../types/archetypes/view_coordinates.md | 4 +- .../types/components/view_coordinates.md | 4 +- .../types/datatypes/view_coordinates.md | 4 +- .../src/rerun/archetypes/view_coordinates.hpp | 64 +++++++++- .../rerun/archetypes/view_coordinates_ext.cpp | 60 +++++++++ .../src/rerun/components/view_coordinates.hpp | 64 +++++++++- .../rerun/components/view_coordinates_ext.cpp | 60 +++++++++ .../src/rerun/datatypes/view_coordinates.hpp | 4 +- .../rerun/archetypes/view_coordinates.py | 4 +- .../rerun/components/view_coordinates.py | 4 +- .../rerun/components/view_coordinates_ext.py | 120 +++++++++++++----- .../rerun/datatypes/view_coordinates.py | 4 +- scripts/generate_view_coordinate_defs.py | 63 +++++++-- 22 files changed, 607 insertions(+), 118 deletions(-) diff --git a/crates/store/re_types/definitions/rerun/archetypes/view_coordinates.fbs b/crates/store/re_types/definitions/rerun/archetypes/view_coordinates.fbs index 733d7fac48c9..88cf09f52a40 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/view_coordinates.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/view_coordinates.fbs @@ -4,7 +4,7 @@ namespace rerun.archetypes; /// How we interpret the coordinate system of an entity/space. /// -/// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +/// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// @@ -13,6 +13,8 @@ namespace rerun.archetypes; /// /// Make sure that this archetype is logged at or above the origin entity path of your 3D views. /// +/// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). +/// /// \example archetypes/view_coordinates_simple title="View coordinates for adjusting the eye camera" image="https://static.rerun.io/viewcoordinates/0833f0dc8616a676b7b2c566f2a6f613363680c5/1200w.png" table ViewCoordinates ( "attr.rust.derive": "Copy, PartialEq, Eq, bytemuck::Pod, bytemuck::Zeroable", diff --git a/crates/store/re_types/definitions/rerun/components/view_coordinates.fbs b/crates/store/re_types/definitions/rerun/components/view_coordinates.fbs index dae19f24c67c..1ff35d3722b1 100644 --- a/crates/store/re_types/definitions/rerun/components/view_coordinates.fbs +++ b/crates/store/re_types/definitions/rerun/components/view_coordinates.fbs @@ -15,13 +15,15 @@ enum ViewDir: ubyte { /// How we interpret the coordinate system of an entity/space. /// -/// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +/// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// /// For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points /// down, and the Z axis points forward. /// +/// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). +/// /// The following constants are used to represent the different directions: /// * Up = 1 /// * Down = 2 diff --git a/crates/store/re_types/definitions/rerun/datatypes/view_coordinates.fbs b/crates/store/re_types/definitions/rerun/datatypes/view_coordinates.fbs index f68f1adcf9af..8e4aecaba5c3 100644 --- a/crates/store/re_types/definitions/rerun/datatypes/view_coordinates.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes/view_coordinates.fbs @@ -15,13 +15,15 @@ enum ViewDir: ubyte { /// How we interpret the coordinate system of an entity/space. /// -/// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +/// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// /// For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points /// down, and the Z axis points forward. /// +/// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). +/// /// The following constants are used to represent the different directions: /// * Up = 1 /// * Down = 2 diff --git a/crates/store/re_types/src/archetypes/view_coordinates.rs b/crates/store/re_types/src/archetypes/view_coordinates.rs index cf42a3e7e37e..b358ef9cdcbb 100644 --- a/crates/store/re_types/src/archetypes/view_coordinates.rs +++ b/crates/store/re_types/src/archetypes/view_coordinates.rs @@ -20,7 +20,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: How we interpret the coordinate system of an entity/space. /// -/// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +/// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// @@ -29,6 +29,8 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// /// Make sure that this archetype is logged at or above the origin entity path of your 3D views. /// +/// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). +/// /// ## Example /// /// ### View coordinates for adjusting the eye camera diff --git a/crates/store/re_types/src/archetypes/view_coordinates_ext.rs b/crates/store/re_types/src/archetypes/view_coordinates_ext.rs index c4c568100810..3961280ab492 100644 --- a/crates/store/re_types/src/archetypes/view_coordinates_ext.rs +++ b/crates/store/re_types/src/archetypes/view_coordinates_ext.rs @@ -14,65 +14,125 @@ macro_rules! define_coordinates { impl ViewCoordinates { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --rust` - define_coordinates!("X=Up, Y=Left, Z=Forward", ULF => (Up, Left, Forward)); + define_coordinates!("X=Up, Y=Left, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", ULF => (Up, Left, Forward)); define_coordinates!("X=Up, Y=Forward, Z=Left", UFL => (Up, Forward, Left)); define_coordinates!("X=Left, Y=Up, Z=Forward", LUF => (Left, Up, Forward)); - define_coordinates!("X=Left, Y=Forward, Z=Up", LFU => (Left, Forward, Up)); - define_coordinates!("X=Forward, Y=Up, Z=Left", FUL => (Forward, Up, Left)); + define_coordinates!("X=Left, Y=Forward, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LFU => (Left, Forward, Up)); + define_coordinates!("X=Forward, Y=Up, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", FUL => (Forward, Up, Left)); define_coordinates!("X=Forward, Y=Left, Z=Up", FLU => (Forward, Left, Up)); define_coordinates!("X=Up, Y=Left, Z=Back", ULB => (Up, Left, Back)); - define_coordinates!("X=Up, Y=Back, Z=Left", UBL => (Up, Back, Left)); - define_coordinates!("X=Left, Y=Up, Z=Back", LUB => (Left, Up, Back)); + define_coordinates!("X=Up, Y=Back, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", UBL => (Up, Back, Left)); + define_coordinates!("X=Left, Y=Up, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LUB => (Left, Up, Back)); define_coordinates!("X=Left, Y=Back, Z=Up", LBU => (Left, Back, Up)); define_coordinates!("X=Back, Y=Up, Z=Left", BUL => (Back, Up, Left)); - define_coordinates!("X=Back, Y=Left, Z=Up", BLU => (Back, Left, Up)); + define_coordinates!("X=Back, Y=Left, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", BLU => (Back, Left, Up)); define_coordinates!("X=Up, Y=Right, Z=Forward", URF => (Up, Right, Forward)); - define_coordinates!("X=Up, Y=Forward, Z=Right", UFR => (Up, Forward, Right)); - define_coordinates!("X=Right, Y=Up, Z=Forward", RUF => (Right, Up, Forward)); + define_coordinates!("X=Up, Y=Forward, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", UFR => (Up, Forward, Right)); + define_coordinates!("X=Right, Y=Up, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", RUF => (Right, Up, Forward)); define_coordinates!("X=Right, Y=Forward, Z=Up", RFU => (Right, Forward, Up)); define_coordinates!("X=Forward, Y=Up, Z=Right", FUR => (Forward, Up, Right)); - define_coordinates!("X=Forward, Y=Right, Z=Up", FRU => (Forward, Right, Up)); - define_coordinates!("X=Up, Y=Right, Z=Back", URB => (Up, Right, Back)); + define_coordinates!("X=Forward, Y=Right, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", FRU => (Forward, Right, Up)); + define_coordinates!("X=Up, Y=Right, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", URB => (Up, Right, Back)); define_coordinates!("X=Up, Y=Back, Z=Right", UBR => (Up, Back, Right)); define_coordinates!("X=Right, Y=Up, Z=Back", RUB => (Right, Up, Back)); - define_coordinates!("X=Right, Y=Back, Z=Up", RBU => (Right, Back, Up)); - define_coordinates!("X=Back, Y=Up, Z=Right", BUR => (Back, Up, Right)); + define_coordinates!("X=Right, Y=Back, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", RBU => (Right, Back, Up)); + define_coordinates!("X=Back, Y=Up, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", BUR => (Back, Up, Right)); define_coordinates!("X=Back, Y=Right, Z=Up", BRU => (Back, Right, Up)); define_coordinates!("X=Down, Y=Left, Z=Forward", DLF => (Down, Left, Forward)); - define_coordinates!("X=Down, Y=Forward, Z=Left", DFL => (Down, Forward, Left)); - define_coordinates!("X=Left, Y=Down, Z=Forward", LDF => (Left, Down, Forward)); + define_coordinates!("X=Down, Y=Forward, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", DFL => (Down, Forward, Left)); + define_coordinates!("X=Left, Y=Down, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LDF => (Left, Down, Forward)); define_coordinates!("X=Left, Y=Forward, Z=Down", LFD => (Left, Forward, Down)); define_coordinates!("X=Forward, Y=Down, Z=Left", FDL => (Forward, Down, Left)); - define_coordinates!("X=Forward, Y=Left, Z=Down", FLD => (Forward, Left, Down)); - define_coordinates!("X=Down, Y=Left, Z=Back", DLB => (Down, Left, Back)); + define_coordinates!("X=Forward, Y=Left, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", FLD => (Forward, Left, Down)); + define_coordinates!("X=Down, Y=Left, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", DLB => (Down, Left, Back)); define_coordinates!("X=Down, Y=Back, Z=Left", DBL => (Down, Back, Left)); define_coordinates!("X=Left, Y=Down, Z=Back", LDB => (Left, Down, Back)); - define_coordinates!("X=Left, Y=Back, Z=Down", LBD => (Left, Back, Down)); - define_coordinates!("X=Back, Y=Down, Z=Left", BDL => (Back, Down, Left)); + define_coordinates!("X=Left, Y=Back, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LBD => (Left, Back, Down)); + define_coordinates!("X=Back, Y=Down, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", BDL => (Back, Down, Left)); define_coordinates!("X=Back, Y=Left, Z=Down", BLD => (Back, Left, Down)); - define_coordinates!("X=Down, Y=Right, Z=Forward", DRF => (Down, Right, Forward)); + define_coordinates!("X=Down, Y=Right, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", DRF => (Down, Right, Forward)); define_coordinates!("X=Down, Y=Forward, Z=Right", DFR => (Down, Forward, Right)); define_coordinates!("X=Right, Y=Down, Z=Forward", RDF => (Right, Down, Forward)); - define_coordinates!("X=Right, Y=Forward, Z=Down", RFD => (Right, Forward, Down)); - define_coordinates!("X=Forward, Y=Down, Z=Right", FDR => (Forward, Down, Right)); + define_coordinates!("X=Right, Y=Forward, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", RFD => (Right, Forward, Down)); + define_coordinates!("X=Forward, Y=Down, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", FDR => (Forward, Down, Right)); define_coordinates!("X=Forward, Y=Right, Z=Down", FRD => (Forward, Right, Down)); define_coordinates!("X=Down, Y=Right, Z=Back", DRB => (Down, Right, Back)); - define_coordinates!("X=Down, Y=Back, Z=Right", DBR => (Down, Back, Right)); - define_coordinates!("X=Right, Y=Down, Z=Back", RDB => (Right, Down, Back)); + define_coordinates!("X=Down, Y=Back, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", DBR => (Down, Back, Right)); + define_coordinates!("X=Right, Y=Down, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", RDB => (Right, Down, Back)); define_coordinates!("X=Right, Y=Back, Z=Down", RBD => (Right, Back, Down)); define_coordinates!("X=Back, Y=Down, Z=Right", BDR => (Back, Down, Right)); - define_coordinates!("X=Back, Y=Right, Z=Down", BRD => (Back, Right, Down)); + define_coordinates!("X=Back, Y=Right, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", BRD => (Back, Right, Down)); define_coordinates!("X=Up, Y=Right, Z=Forward", RIGHT_HAND_X_UP => (Up, Right, Forward)); define_coordinates!("X=Down, Y=Right, Z=Back", RIGHT_HAND_X_DOWN => (Down, Right, Back)); define_coordinates!("X=Right, Y=Up, Z=Back", RIGHT_HAND_Y_UP => (Right, Up, Back)); define_coordinates!("X=Right, Y=Down, Z=Forward", RIGHT_HAND_Y_DOWN => (Right, Down, Forward)); define_coordinates!("X=Right, Y=Forward, Z=Up", RIGHT_HAND_Z_UP => (Right, Forward, Up)); define_coordinates!("X=Right, Y=Back, Z=Down", RIGHT_HAND_Z_DOWN => (Right, Back, Down)); - define_coordinates!("X=Up, Y=Right, Z=Back", LEFT_HAND_X_UP => (Up, Right, Back)); - define_coordinates!("X=Down, Y=Right, Z=Forward", LEFT_HAND_X_DOWN => (Down, Right, Forward)); - define_coordinates!("X=Right, Y=Up, Z=Forward", LEFT_HAND_Y_UP => (Right, Up, Forward)); - define_coordinates!("X=Right, Y=Down, Z=Back", LEFT_HAND_Y_DOWN => (Right, Down, Back)); - define_coordinates!("X=Right, Y=Back, Z=Up", LEFT_HAND_Z_UP => (Right, Back, Up)); - define_coordinates!("X=Right, Y=Forward, Z=Down", LEFT_HAND_Z_DOWN => (Right, Forward, Down)); + define_coordinates!("X=Up, Y=Right, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_X_UP => (Up, Right, Back)); + define_coordinates!("X=Down, Y=Right, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_X_DOWN => (Down, Right, Forward)); + define_coordinates!("X=Right, Y=Up, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_Y_UP => (Right, Up, Forward)); + define_coordinates!("X=Right, Y=Down, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_Y_DOWN => (Right, Down, Back)); + define_coordinates!("X=Right, Y=Back, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_Z_UP => (Right, Back, Up)); + define_coordinates!("X=Right, Y=Forward, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_Z_DOWN => (Right, Forward, Down)); // } diff --git a/crates/store/re_types/src/components/view_coordinates.rs b/crates/store/re_types/src/components/view_coordinates.rs index e2e19b78de3e..1fece1f587dc 100644 --- a/crates/store/re_types/src/components/view_coordinates.rs +++ b/crates/store/re_types/src/components/view_coordinates.rs @@ -20,13 +20,15 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Component**: How we interpret the coordinate system of an entity/space. /// -/// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +/// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// /// For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points /// down, and the Z axis points forward. /// +/// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). +/// /// The following constants are used to represent the different directions: /// * Up = 1 /// * Down = 2 diff --git a/crates/store/re_types/src/components/view_coordinates_ext.rs b/crates/store/re_types/src/components/view_coordinates_ext.rs index 3d4342816c21..f5eaa0e1a3e0 100644 --- a/crates/store/re_types/src/components/view_coordinates_ext.rs +++ b/crates/store/re_types/src/components/view_coordinates_ext.rs @@ -284,65 +284,125 @@ macro_rules! define_coordinates { impl ViewCoordinates { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --rust` - define_coordinates!("X=Up, Y=Left, Z=Forward", ULF => (Up, Left, Forward)); + define_coordinates!("X=Up, Y=Left, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", ULF => (Up, Left, Forward)); define_coordinates!("X=Up, Y=Forward, Z=Left", UFL => (Up, Forward, Left)); define_coordinates!("X=Left, Y=Up, Z=Forward", LUF => (Left, Up, Forward)); - define_coordinates!("X=Left, Y=Forward, Z=Up", LFU => (Left, Forward, Up)); - define_coordinates!("X=Forward, Y=Up, Z=Left", FUL => (Forward, Up, Left)); + define_coordinates!("X=Left, Y=Forward, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LFU => (Left, Forward, Up)); + define_coordinates!("X=Forward, Y=Up, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", FUL => (Forward, Up, Left)); define_coordinates!("X=Forward, Y=Left, Z=Up", FLU => (Forward, Left, Up)); define_coordinates!("X=Up, Y=Left, Z=Back", ULB => (Up, Left, Back)); - define_coordinates!("X=Up, Y=Back, Z=Left", UBL => (Up, Back, Left)); - define_coordinates!("X=Left, Y=Up, Z=Back", LUB => (Left, Up, Back)); + define_coordinates!("X=Up, Y=Back, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", UBL => (Up, Back, Left)); + define_coordinates!("X=Left, Y=Up, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LUB => (Left, Up, Back)); define_coordinates!("X=Left, Y=Back, Z=Up", LBU => (Left, Back, Up)); define_coordinates!("X=Back, Y=Up, Z=Left", BUL => (Back, Up, Left)); - define_coordinates!("X=Back, Y=Left, Z=Up", BLU => (Back, Left, Up)); + define_coordinates!("X=Back, Y=Left, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", BLU => (Back, Left, Up)); define_coordinates!("X=Up, Y=Right, Z=Forward", URF => (Up, Right, Forward)); - define_coordinates!("X=Up, Y=Forward, Z=Right", UFR => (Up, Forward, Right)); - define_coordinates!("X=Right, Y=Up, Z=Forward", RUF => (Right, Up, Forward)); + define_coordinates!("X=Up, Y=Forward, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", UFR => (Up, Forward, Right)); + define_coordinates!("X=Right, Y=Up, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", RUF => (Right, Up, Forward)); define_coordinates!("X=Right, Y=Forward, Z=Up", RFU => (Right, Forward, Up)); define_coordinates!("X=Forward, Y=Up, Z=Right", FUR => (Forward, Up, Right)); - define_coordinates!("X=Forward, Y=Right, Z=Up", FRU => (Forward, Right, Up)); - define_coordinates!("X=Up, Y=Right, Z=Back", URB => (Up, Right, Back)); + define_coordinates!("X=Forward, Y=Right, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", FRU => (Forward, Right, Up)); + define_coordinates!("X=Up, Y=Right, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", URB => (Up, Right, Back)); define_coordinates!("X=Up, Y=Back, Z=Right", UBR => (Up, Back, Right)); define_coordinates!("X=Right, Y=Up, Z=Back", RUB => (Right, Up, Back)); - define_coordinates!("X=Right, Y=Back, Z=Up", RBU => (Right, Back, Up)); - define_coordinates!("X=Back, Y=Up, Z=Right", BUR => (Back, Up, Right)); + define_coordinates!("X=Right, Y=Back, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", RBU => (Right, Back, Up)); + define_coordinates!("X=Back, Y=Up, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", BUR => (Back, Up, Right)); define_coordinates!("X=Back, Y=Right, Z=Up", BRU => (Back, Right, Up)); define_coordinates!("X=Down, Y=Left, Z=Forward", DLF => (Down, Left, Forward)); - define_coordinates!("X=Down, Y=Forward, Z=Left", DFL => (Down, Forward, Left)); - define_coordinates!("X=Left, Y=Down, Z=Forward", LDF => (Left, Down, Forward)); + define_coordinates!("X=Down, Y=Forward, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", DFL => (Down, Forward, Left)); + define_coordinates!("X=Left, Y=Down, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LDF => (Left, Down, Forward)); define_coordinates!("X=Left, Y=Forward, Z=Down", LFD => (Left, Forward, Down)); define_coordinates!("X=Forward, Y=Down, Z=Left", FDL => (Forward, Down, Left)); - define_coordinates!("X=Forward, Y=Left, Z=Down", FLD => (Forward, Left, Down)); - define_coordinates!("X=Down, Y=Left, Z=Back", DLB => (Down, Left, Back)); + define_coordinates!("X=Forward, Y=Left, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", FLD => (Forward, Left, Down)); + define_coordinates!("X=Down, Y=Left, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", DLB => (Down, Left, Back)); define_coordinates!("X=Down, Y=Back, Z=Left", DBL => (Down, Back, Left)); define_coordinates!("X=Left, Y=Down, Z=Back", LDB => (Left, Down, Back)); - define_coordinates!("X=Left, Y=Back, Z=Down", LBD => (Left, Back, Down)); - define_coordinates!("X=Back, Y=Down, Z=Left", BDL => (Back, Down, Left)); + define_coordinates!("X=Left, Y=Back, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LBD => (Left, Back, Down)); + define_coordinates!("X=Back, Y=Down, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", BDL => (Back, Down, Left)); define_coordinates!("X=Back, Y=Left, Z=Down", BLD => (Back, Left, Down)); - define_coordinates!("X=Down, Y=Right, Z=Forward", DRF => (Down, Right, Forward)); + define_coordinates!("X=Down, Y=Right, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", DRF => (Down, Right, Forward)); define_coordinates!("X=Down, Y=Forward, Z=Right", DFR => (Down, Forward, Right)); define_coordinates!("X=Right, Y=Down, Z=Forward", RDF => (Right, Down, Forward)); - define_coordinates!("X=Right, Y=Forward, Z=Down", RFD => (Right, Forward, Down)); - define_coordinates!("X=Forward, Y=Down, Z=Right", FDR => (Forward, Down, Right)); + define_coordinates!("X=Right, Y=Forward, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", RFD => (Right, Forward, Down)); + define_coordinates!("X=Forward, Y=Down, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", FDR => (Forward, Down, Right)); define_coordinates!("X=Forward, Y=Right, Z=Down", FRD => (Forward, Right, Down)); define_coordinates!("X=Down, Y=Right, Z=Back", DRB => (Down, Right, Back)); - define_coordinates!("X=Down, Y=Back, Z=Right", DBR => (Down, Back, Right)); - define_coordinates!("X=Right, Y=Down, Z=Back", RDB => (Right, Down, Back)); + define_coordinates!("X=Down, Y=Back, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", DBR => (Down, Back, Right)); + define_coordinates!("X=Right, Y=Down, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", RDB => (Right, Down, Back)); define_coordinates!("X=Right, Y=Back, Z=Down", RBD => (Right, Back, Down)); define_coordinates!("X=Back, Y=Down, Z=Right", BDR => (Back, Down, Right)); - define_coordinates!("X=Back, Y=Right, Z=Down", BRD => (Back, Right, Down)); + define_coordinates!("X=Back, Y=Right, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", BRD => (Back, Right, Down)); define_coordinates!("X=Up, Y=Right, Z=Forward", RIGHT_HAND_X_UP => (Up, Right, Forward)); define_coordinates!("X=Down, Y=Right, Z=Back", RIGHT_HAND_X_DOWN => (Down, Right, Back)); define_coordinates!("X=Right, Y=Up, Z=Back", RIGHT_HAND_Y_UP => (Right, Up, Back)); define_coordinates!("X=Right, Y=Down, Z=Forward", RIGHT_HAND_Y_DOWN => (Right, Down, Forward)); define_coordinates!("X=Right, Y=Forward, Z=Up", RIGHT_HAND_Z_UP => (Right, Forward, Up)); define_coordinates!("X=Right, Y=Back, Z=Down", RIGHT_HAND_Z_DOWN => (Right, Back, Down)); - define_coordinates!("X=Up, Y=Right, Z=Back", LEFT_HAND_X_UP => (Up, Right, Back)); - define_coordinates!("X=Down, Y=Right, Z=Forward", LEFT_HAND_X_DOWN => (Down, Right, Forward)); - define_coordinates!("X=Right, Y=Up, Z=Forward", LEFT_HAND_Y_UP => (Right, Up, Forward)); - define_coordinates!("X=Right, Y=Down, Z=Back", LEFT_HAND_Y_DOWN => (Right, Down, Back)); - define_coordinates!("X=Right, Y=Back, Z=Up", LEFT_HAND_Z_UP => (Right, Back, Up)); - define_coordinates!("X=Right, Y=Forward, Z=Down", LEFT_HAND_Z_DOWN => (Right, Forward, Down)); + define_coordinates!("X=Up, Y=Right, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_X_UP => (Up, Right, Back)); + define_coordinates!("X=Down, Y=Right, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_X_DOWN => (Down, Right, Forward)); + define_coordinates!("X=Right, Y=Up, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_Y_UP => (Right, Up, Forward)); + define_coordinates!("X=Right, Y=Down, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_Y_DOWN => (Right, Down, Back)); + define_coordinates!("X=Right, Y=Back, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_Z_UP => (Right, Back, Up)); + define_coordinates!("X=Right, Y=Forward, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).", LEFT_HAND_Z_DOWN => (Right, Forward, Down)); // } diff --git a/crates/store/re_types/src/datatypes/view_coordinates.rs b/crates/store/re_types/src/datatypes/view_coordinates.rs index 1da2ae98aea0..ce99e676e6b7 100644 --- a/crates/store/re_types/src/datatypes/view_coordinates.rs +++ b/crates/store/re_types/src/datatypes/view_coordinates.rs @@ -20,13 +20,15 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Datatype**: How we interpret the coordinate system of an entity/space. /// -/// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +/// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// /// For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points /// down, and the Z axis points forward. /// +/// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). +/// /// The following constants are used to represent the different directions: /// * Up = 1 /// * Down = 2 diff --git a/crates/viewer/re_viewer/src/reflection/mod.rs b/crates/viewer/re_viewer/src/reflection/mod.rs index 24d6a1935d60..025522c5253d 100644 --- a/crates/viewer/re_viewer/src/reflection/mod.rs +++ b/crates/viewer/re_viewer/src/reflection/mod.rs @@ -695,7 +695,7 @@ fn generate_component_reflection() -> Result::name(), ComponentReflection { - docstring_md: "How we interpret the coordinate system of an entity/space.\n\nFor instance: What is \"up\"? What does the Z axis mean? Is this right-handed or left-handed?\n\nThe three coordinates are always ordered as [x, y, z].\n\nFor example [Right, Down, Forward] means that the X axis points to the right, the Y axis points\ndown, and the Z axis points forward.\n\nThe following constants are used to represent the different directions:\n * Up = 1\n * Down = 2\n * Right = 3\n * Left = 4\n * Forward = 5\n * Back = 6", + docstring_md: "How we interpret the coordinate system of an entity/space.\n\nFor instance: What is \"up\"? What does the Z axis mean?\n\nThe three coordinates are always ordered as [x, y, z].\n\nFor example [Right, Down, Forward] means that the X axis points to the right, the Y axis points\ndown, and the Z axis points forward.\n\n⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032).\n\nThe following constants are used to represent the different directions:\n * Up = 1\n * Down = 2\n * Right = 3\n * Left = 4\n * Forward = 5\n * Back = 6", placeholder: Some(ViewCoordinates::default().to_arrow()?), }, ), diff --git a/docs/content/reference/types/archetypes/view_coordinates.md b/docs/content/reference/types/archetypes/view_coordinates.md index 68d44f93d9f4..544fd552f529 100644 --- a/docs/content/reference/types/archetypes/view_coordinates.md +++ b/docs/content/reference/types/archetypes/view_coordinates.md @@ -5,7 +5,7 @@ title: "ViewCoordinates" How we interpret the coordinate system of an entity/space. -For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. @@ -14,6 +14,8 @@ down, and the Z axis points forward. Make sure that this archetype is logged at or above the origin entity path of your 3D views. +⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + ## Components **Required**: [`ViewCoordinates`](../components/view_coordinates.md) diff --git a/docs/content/reference/types/components/view_coordinates.md b/docs/content/reference/types/components/view_coordinates.md index ad993b0098ac..567b88663c15 100644 --- a/docs/content/reference/types/components/view_coordinates.md +++ b/docs/content/reference/types/components/view_coordinates.md @@ -5,13 +5,15 @@ title: "ViewCoordinates" How we interpret the coordinate system of an entity/space. -For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points down, and the Z axis points forward. +⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + The following constants are used to represent the different directions: * Up = 1 * Down = 2 diff --git a/docs/content/reference/types/datatypes/view_coordinates.md b/docs/content/reference/types/datatypes/view_coordinates.md index a3eeb9e5fb1d..bf2b806b42cd 100644 --- a/docs/content/reference/types/datatypes/view_coordinates.md +++ b/docs/content/reference/types/datatypes/view_coordinates.md @@ -5,13 +5,15 @@ title: "ViewCoordinates" How we interpret the coordinate system of an entity/space. -For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? +For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points down, and the Z axis points forward. +⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + The following constants are used to represent the different directions: * Up = 1 * Down = 2 diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp index 779a54a632fc..e23893a79f89 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates.hpp @@ -17,7 +17,7 @@ namespace rerun::archetypes { /// **Archetype**: How we interpret the coordinate system of an entity/space. /// - /// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? + /// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// @@ -26,6 +26,8 @@ namespace rerun::archetypes { /// /// Make sure that this archetype is logged at or above the origin entity path of your 3D views. /// + /// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + /// /// ## Example /// /// ### View coordinates for adjusting the eye camera @@ -65,6 +67,8 @@ namespace rerun::archetypes { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` /// X=Up, Y=Left, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULF; /// X=Up, Y=Forward, Z=Left @@ -74,9 +78,13 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUF; /// X=Left, Y=Forward, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFU; /// X=Forward, Y=Up, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUL; /// X=Forward, Y=Left, Z=Up @@ -86,9 +94,13 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULB; /// X=Up, Y=Back, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBL; /// X=Left, Y=Up, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUB; /// X=Left, Y=Back, Z=Up @@ -98,15 +110,21 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUL; /// X=Back, Y=Left, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLU; /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URF; /// X=Up, Y=Forward, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFR; /// X=Right, Y=Up, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUF; /// X=Right, Y=Forward, Z=Up @@ -116,9 +134,13 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUR; /// X=Forward, Y=Right, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRU; /// X=Up, Y=Right, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URB; /// X=Up, Y=Back, Z=Right @@ -128,9 +150,13 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUB; /// X=Right, Y=Back, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBU; /// X=Back, Y=Up, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUR; /// X=Back, Y=Right, Z=Up @@ -140,9 +166,13 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLF; /// X=Down, Y=Forward, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFL; /// X=Left, Y=Down, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDF; /// X=Left, Y=Forward, Z=Down @@ -152,9 +182,13 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDL; /// X=Forward, Y=Left, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLD; /// X=Down, Y=Left, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLB; /// X=Down, Y=Back, Z=Left @@ -164,15 +198,21 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDB; /// X=Left, Y=Back, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBD; /// X=Back, Y=Down, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDL; /// X=Back, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLD; /// X=Down, Y=Right, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRF; /// X=Down, Y=Forward, Z=Right @@ -182,9 +222,13 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDF; /// X=Right, Y=Forward, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFD; /// X=Forward, Y=Down, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDR; /// X=Forward, Y=Right, Z=Down @@ -194,9 +238,13 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRB; /// X=Down, Y=Back, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBR; /// X=Right, Y=Down, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDB; /// X=Right, Y=Back, Z=Down @@ -206,6 +254,8 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDR; /// X=Back, Y=Right, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRD; /// X=Up, Y=Right, Z=Forward @@ -227,21 +277,33 @@ namespace rerun::archetypes { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_DOWN; /// X=Up, Y=Right, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_UP; /// X=Down, Y=Right, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_DOWN; /// X=Right, Y=Up, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_UP; /// X=Right, Y=Down, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_DOWN; /// X=Right, Y=Back, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_UP; /// X=Right, Y=Forward, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_DOWN; // diff --git a/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp b/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp index 31de3b47e54b..484f0bb3f0b1 100644 --- a/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/view_coordinates_ext.cpp @@ -25,6 +25,8 @@ namespace rerun { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` /// X=Up, Y=Left, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULF; /// X=Up, Y=Forward, Z=Left @@ -34,9 +36,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUF; /// X=Left, Y=Forward, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LFU; /// X=Forward, Y=Up, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUL; /// X=Forward, Y=Left, Z=Up @@ -46,9 +52,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates ULB; /// X=Up, Y=Back, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UBL; /// X=Left, Y=Up, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LUB; /// X=Left, Y=Back, Z=Up @@ -58,15 +68,21 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUL; /// X=Back, Y=Left, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLU; /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URF; /// X=Up, Y=Forward, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates UFR; /// X=Right, Y=Up, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUF; /// X=Right, Y=Forward, Z=Up @@ -76,9 +92,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FUR; /// X=Forward, Y=Right, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FRU; /// X=Up, Y=Right, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates URB; /// X=Up, Y=Back, Z=Right @@ -88,9 +108,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RUB; /// X=Right, Y=Back, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RBU; /// X=Back, Y=Up, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BUR; /// X=Back, Y=Right, Z=Up @@ -100,9 +124,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLF; /// X=Down, Y=Forward, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DFL; /// X=Left, Y=Down, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDF; /// X=Left, Y=Forward, Z=Down @@ -112,9 +140,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDL; /// X=Forward, Y=Left, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FLD; /// X=Down, Y=Left, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DLB; /// X=Down, Y=Back, Z=Left @@ -124,15 +156,21 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LDB; /// X=Left, Y=Back, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LBD; /// X=Back, Y=Down, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDL; /// X=Back, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BLD; /// X=Down, Y=Right, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRF; /// X=Down, Y=Forward, Z=Right @@ -142,9 +180,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDF; /// X=Right, Y=Forward, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RFD; /// X=Forward, Y=Down, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates FDR; /// X=Forward, Y=Right, Z=Down @@ -154,9 +196,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DRB; /// X=Down, Y=Back, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates DBR; /// X=Right, Y=Down, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RDB; /// X=Right, Y=Back, Z=Down @@ -166,6 +212,8 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BDR; /// X=Back, Y=Right, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates BRD; /// X=Up, Y=Right, Z=Forward @@ -187,21 +235,33 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates RIGHT_HAND_Z_DOWN; /// X=Up, Y=Right, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_UP; /// X=Down, Y=Right, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_X_DOWN; /// X=Right, Y=Up, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_UP; /// X=Right, Y=Down, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Y_DOWN; /// X=Right, Y=Back, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_UP; /// X=Right, Y=Forward, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates LEFT_HAND_Z_DOWN; // diff --git a/rerun_cpp/src/rerun/components/view_coordinates.hpp b/rerun_cpp/src/rerun/components/view_coordinates.hpp index 849fe074cbe9..5485e1aae665 100644 --- a/rerun_cpp/src/rerun/components/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/components/view_coordinates.hpp @@ -13,13 +13,15 @@ namespace rerun::components { /// **Component**: How we interpret the coordinate system of an entity/space. /// - /// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? + /// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// /// For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points /// down, and the Z axis points forward. /// + /// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + /// /// The following constants are used to represent the different directions: /// * Up = 1 /// * Down = 2 @@ -52,6 +54,8 @@ namespace rerun::components { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` /// X=Up, Y=Left, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULF; /// X=Up, Y=Forward, Z=Left @@ -61,9 +65,13 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUF; /// X=Left, Y=Forward, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFU; /// X=Forward, Y=Up, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUL; /// X=Forward, Y=Left, Z=Up @@ -73,9 +81,13 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULB; /// X=Up, Y=Back, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBL; /// X=Left, Y=Up, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUB; /// X=Left, Y=Back, Z=Up @@ -85,15 +97,21 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUL; /// X=Back, Y=Left, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLU; /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URF; /// X=Up, Y=Forward, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFR; /// X=Right, Y=Up, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUF; /// X=Right, Y=Forward, Z=Up @@ -103,9 +121,13 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUR; /// X=Forward, Y=Right, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRU; /// X=Up, Y=Right, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URB; /// X=Up, Y=Back, Z=Right @@ -115,9 +137,13 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUB; /// X=Right, Y=Back, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBU; /// X=Back, Y=Up, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUR; /// X=Back, Y=Right, Z=Up @@ -127,9 +153,13 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLF; /// X=Down, Y=Forward, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFL; /// X=Left, Y=Down, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDF; /// X=Left, Y=Forward, Z=Down @@ -139,9 +169,13 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDL; /// X=Forward, Y=Left, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLD; /// X=Down, Y=Left, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLB; /// X=Down, Y=Back, Z=Left @@ -151,15 +185,21 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDB; /// X=Left, Y=Back, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBD; /// X=Back, Y=Down, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDL; /// X=Back, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLD; /// X=Down, Y=Right, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRF; /// X=Down, Y=Forward, Z=Right @@ -169,9 +209,13 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDF; /// X=Right, Y=Forward, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFD; /// X=Forward, Y=Down, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDR; /// X=Forward, Y=Right, Z=Down @@ -181,9 +225,13 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRB; /// X=Down, Y=Back, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBR; /// X=Right, Y=Down, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDB; /// X=Right, Y=Back, Z=Down @@ -193,6 +241,8 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDR; /// X=Back, Y=Right, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRD; /// X=Up, Y=Right, Z=Forward @@ -214,21 +264,33 @@ namespace rerun::components { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_DOWN; /// X=Up, Y=Right, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_UP; /// X=Down, Y=Right, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_DOWN; /// X=Right, Y=Up, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_UP; /// X=Right, Y=Down, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_DOWN; /// X=Right, Y=Back, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_UP; /// X=Right, Y=Forward, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_DOWN; // diff --git a/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp b/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp index c36d1f6f487d..c2d891c709a7 100644 --- a/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp +++ b/rerun_cpp/src/rerun/components/view_coordinates_ext.cpp @@ -38,6 +38,8 @@ namespace rerun { // // This section is generated by running `scripts/generate_view_coordinate_defs.py --cpp` /// X=Up, Y=Left, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULF; /// X=Up, Y=Forward, Z=Left @@ -47,9 +49,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUF; /// X=Left, Y=Forward, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LFU; /// X=Forward, Y=Up, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUL; /// X=Forward, Y=Left, Z=Up @@ -59,9 +65,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates ULB; /// X=Up, Y=Back, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UBL; /// X=Left, Y=Up, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LUB; /// X=Left, Y=Back, Z=Up @@ -71,15 +81,21 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUL; /// X=Back, Y=Left, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLU; /// X=Up, Y=Right, Z=Forward RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URF; /// X=Up, Y=Forward, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates UFR; /// X=Right, Y=Up, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUF; /// X=Right, Y=Forward, Z=Up @@ -89,9 +105,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FUR; /// X=Forward, Y=Right, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FRU; /// X=Up, Y=Right, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates URB; /// X=Up, Y=Back, Z=Right @@ -101,9 +121,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RUB; /// X=Right, Y=Back, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RBU; /// X=Back, Y=Up, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BUR; /// X=Back, Y=Right, Z=Up @@ -113,9 +137,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLF; /// X=Down, Y=Forward, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DFL; /// X=Left, Y=Down, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDF; /// X=Left, Y=Forward, Z=Down @@ -125,9 +153,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDL; /// X=Forward, Y=Left, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FLD; /// X=Down, Y=Left, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DLB; /// X=Down, Y=Back, Z=Left @@ -137,15 +169,21 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LDB; /// X=Left, Y=Back, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LBD; /// X=Back, Y=Down, Z=Left + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDL; /// X=Back, Y=Left, Z=Down RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BLD; /// X=Down, Y=Right, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRF; /// X=Down, Y=Forward, Z=Right @@ -155,9 +193,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDF; /// X=Right, Y=Forward, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RFD; /// X=Forward, Y=Down, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates FDR; /// X=Forward, Y=Right, Z=Down @@ -167,9 +209,13 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DRB; /// X=Down, Y=Back, Z=Right + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates DBR; /// X=Right, Y=Down, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RDB; /// X=Right, Y=Back, Z=Down @@ -179,6 +225,8 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BDR; /// X=Back, Y=Right, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates BRD; /// X=Up, Y=Right, Z=Forward @@ -200,21 +248,33 @@ namespace rerun { RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates RIGHT_HAND_Z_DOWN; /// X=Up, Y=Right, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_UP; /// X=Down, Y=Right, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_X_DOWN; /// X=Right, Y=Up, Z=Forward + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_UP; /// X=Right, Y=Down, Z=Back + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Y_DOWN; /// X=Right, Y=Back, Z=Up + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_UP; /// X=Right, Y=Forward, Z=Down + /// + /// ⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032). RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates LEFT_HAND_Z_DOWN; // diff --git a/rerun_cpp/src/rerun/datatypes/view_coordinates.hpp b/rerun_cpp/src/rerun/datatypes/view_coordinates.hpp index 1ed6a59d77a8..a614773307ef 100644 --- a/rerun_cpp/src/rerun/datatypes/view_coordinates.hpp +++ b/rerun_cpp/src/rerun/datatypes/view_coordinates.hpp @@ -18,13 +18,15 @@ namespace arrow { namespace rerun::datatypes { /// **Datatype**: How we interpret the coordinate system of an entity/space. /// - /// For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? + /// For instance: What is "up"? What does the Z axis mean? /// /// The three coordinates are always ordered as [x, y, z]. /// /// For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points /// down, and the Z axis points forward. /// + /// ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + /// /// The following constants are used to represent the different directions: /// * Up = 1 /// * Down = 2 diff --git a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py index 5f28f6ccc80c..ada329cf25a9 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py @@ -24,7 +24,7 @@ class ViewCoordinates(ViewCoordinatesExt, Archetype): """ **Archetype**: How we interpret the coordinate system of an entity/space. - For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? + For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. @@ -33,6 +33,8 @@ class ViewCoordinates(ViewCoordinatesExt, Archetype): Make sure that this archetype is logged at or above the origin entity path of your 3D views. + ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + Example ------- ### View coordinates for adjusting the eye camera: diff --git a/rerun_py/rerun_sdk/rerun/components/view_coordinates.py b/rerun_py/rerun_sdk/rerun/components/view_coordinates.py index 9824eb7506e6..ea0c1e89d2d7 100644 --- a/rerun_py/rerun_sdk/rerun/components/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/components/view_coordinates.py @@ -19,13 +19,15 @@ class ViewCoordinates(ViewCoordinatesExt, datatypes.ViewCoordinates, ComponentMi """ **Component**: How we interpret the coordinate system of an entity/space. - For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? + For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points down, and the Z axis points forward. + ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + The following constants are used to represent the different directions: * Up = 1 * Down = 2 diff --git a/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py b/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py index 6a699de6611e..abc1559fde84 100644 --- a/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py +++ b/rerun_py/rerun_sdk/rerun/components/view_coordinates_ext.py @@ -44,7 +44,9 @@ def num_instances(self) -> int: # This section is generated by running `scripts/generate_view_coordinate_defs.py --python` # The following declarations are replaced in `deferred_patch_class`. ULF: ViewCoordinates = None # type: ignore[assignment] - """X=Up, Y=Left, Z=Forward""" + """X=Up, Y=Left, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" UFL: ViewCoordinates = None # type: ignore[assignment] """X=Up, Y=Forward, Z=Left""" @@ -53,10 +55,14 @@ def num_instances(self) -> int: """X=Left, Y=Up, Z=Forward""" LFU: ViewCoordinates = None # type: ignore[assignment] - """X=Left, Y=Forward, Z=Up""" + """X=Left, Y=Forward, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" FUL: ViewCoordinates = None # type: ignore[assignment] - """X=Forward, Y=Up, Z=Left""" + """X=Forward, Y=Up, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" FLU: ViewCoordinates = None # type: ignore[assignment] """X=Forward, Y=Left, Z=Up""" @@ -65,10 +71,14 @@ def num_instances(self) -> int: """X=Up, Y=Left, Z=Back""" UBL: ViewCoordinates = None # type: ignore[assignment] - """X=Up, Y=Back, Z=Left""" + """X=Up, Y=Back, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LUB: ViewCoordinates = None # type: ignore[assignment] - """X=Left, Y=Up, Z=Back""" + """X=Left, Y=Up, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LBU: ViewCoordinates = None # type: ignore[assignment] """X=Left, Y=Back, Z=Up""" @@ -77,16 +87,22 @@ def num_instances(self) -> int: """X=Back, Y=Up, Z=Left""" BLU: ViewCoordinates = None # type: ignore[assignment] - """X=Back, Y=Left, Z=Up""" + """X=Back, Y=Left, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" URF: ViewCoordinates = None # type: ignore[assignment] """X=Up, Y=Right, Z=Forward""" UFR: ViewCoordinates = None # type: ignore[assignment] - """X=Up, Y=Forward, Z=Right""" + """X=Up, Y=Forward, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" RUF: ViewCoordinates = None # type: ignore[assignment] - """X=Right, Y=Up, Z=Forward""" + """X=Right, Y=Up, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" RFU: ViewCoordinates = None # type: ignore[assignment] """X=Right, Y=Forward, Z=Up""" @@ -95,10 +111,14 @@ def num_instances(self) -> int: """X=Forward, Y=Up, Z=Right""" FRU: ViewCoordinates = None # type: ignore[assignment] - """X=Forward, Y=Right, Z=Up""" + """X=Forward, Y=Right, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" URB: ViewCoordinates = None # type: ignore[assignment] - """X=Up, Y=Right, Z=Back""" + """X=Up, Y=Right, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" UBR: ViewCoordinates = None # type: ignore[assignment] """X=Up, Y=Back, Z=Right""" @@ -107,10 +127,14 @@ def num_instances(self) -> int: """X=Right, Y=Up, Z=Back""" RBU: ViewCoordinates = None # type: ignore[assignment] - """X=Right, Y=Back, Z=Up""" + """X=Right, Y=Back, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" BUR: ViewCoordinates = None # type: ignore[assignment] - """X=Back, Y=Up, Z=Right""" + """X=Back, Y=Up, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" BRU: ViewCoordinates = None # type: ignore[assignment] """X=Back, Y=Right, Z=Up""" @@ -119,10 +143,14 @@ def num_instances(self) -> int: """X=Down, Y=Left, Z=Forward""" DFL: ViewCoordinates = None # type: ignore[assignment] - """X=Down, Y=Forward, Z=Left""" + """X=Down, Y=Forward, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LDF: ViewCoordinates = None # type: ignore[assignment] - """X=Left, Y=Down, Z=Forward""" + """X=Left, Y=Down, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LFD: ViewCoordinates = None # type: ignore[assignment] """X=Left, Y=Forward, Z=Down""" @@ -131,10 +159,14 @@ def num_instances(self) -> int: """X=Forward, Y=Down, Z=Left""" FLD: ViewCoordinates = None # type: ignore[assignment] - """X=Forward, Y=Left, Z=Down""" + """X=Forward, Y=Left, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" DLB: ViewCoordinates = None # type: ignore[assignment] - """X=Down, Y=Left, Z=Back""" + """X=Down, Y=Left, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" DBL: ViewCoordinates = None # type: ignore[assignment] """X=Down, Y=Back, Z=Left""" @@ -143,16 +175,22 @@ def num_instances(self) -> int: """X=Left, Y=Down, Z=Back""" LBD: ViewCoordinates = None # type: ignore[assignment] - """X=Left, Y=Back, Z=Down""" + """X=Left, Y=Back, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" BDL: ViewCoordinates = None # type: ignore[assignment] - """X=Back, Y=Down, Z=Left""" + """X=Back, Y=Down, Z=Left + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" BLD: ViewCoordinates = None # type: ignore[assignment] """X=Back, Y=Left, Z=Down""" DRF: ViewCoordinates = None # type: ignore[assignment] - """X=Down, Y=Right, Z=Forward""" + """X=Down, Y=Right, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" DFR: ViewCoordinates = None # type: ignore[assignment] """X=Down, Y=Forward, Z=Right""" @@ -161,10 +199,14 @@ def num_instances(self) -> int: """X=Right, Y=Down, Z=Forward""" RFD: ViewCoordinates = None # type: ignore[assignment] - """X=Right, Y=Forward, Z=Down""" + """X=Right, Y=Forward, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" FDR: ViewCoordinates = None # type: ignore[assignment] - """X=Forward, Y=Down, Z=Right""" + """X=Forward, Y=Down, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" FRD: ViewCoordinates = None # type: ignore[assignment] """X=Forward, Y=Right, Z=Down""" @@ -173,10 +215,14 @@ def num_instances(self) -> int: """X=Down, Y=Right, Z=Back""" DBR: ViewCoordinates = None # type: ignore[assignment] - """X=Down, Y=Back, Z=Right""" + """X=Down, Y=Back, Z=Right + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" RDB: ViewCoordinates = None # type: ignore[assignment] - """X=Right, Y=Down, Z=Back""" + """X=Right, Y=Down, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" RBD: ViewCoordinates = None # type: ignore[assignment] """X=Right, Y=Back, Z=Down""" @@ -185,7 +231,9 @@ def num_instances(self) -> int: """X=Back, Y=Down, Z=Right""" BRD: ViewCoordinates = None # type: ignore[assignment] - """X=Back, Y=Right, Z=Down""" + """X=Back, Y=Right, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" RIGHT_HAND_X_UP: ViewCoordinates = None # type: ignore[assignment] """X=Up, Y=Right, Z=Forward""" @@ -206,22 +254,34 @@ def num_instances(self) -> int: """X=Right, Y=Back, Z=Down""" LEFT_HAND_X_UP: ViewCoordinates = None # type: ignore[assignment] - """X=Up, Y=Right, Z=Back""" + """X=Up, Y=Right, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LEFT_HAND_X_DOWN: ViewCoordinates = None # type: ignore[assignment] - """X=Down, Y=Right, Z=Forward""" + """X=Down, Y=Right, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LEFT_HAND_Y_UP: ViewCoordinates = None # type: ignore[assignment] - """X=Right, Y=Up, Z=Forward""" + """X=Right, Y=Up, Z=Forward + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LEFT_HAND_Y_DOWN: ViewCoordinates = None # type: ignore[assignment] - """X=Right, Y=Down, Z=Back""" + """X=Right, Y=Down, Z=Back + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LEFT_HAND_Z_UP: ViewCoordinates = None # type: ignore[assignment] - """X=Right, Y=Back, Z=Up""" + """X=Right, Y=Back, Z=Up + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" LEFT_HAND_Z_DOWN: ViewCoordinates = None # type: ignore[assignment] - """X=Right, Y=Forward, Z=Down""" + """X=Right, Y=Forward, Z=Down + +⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032).""" # diff --git a/rerun_py/rerun_sdk/rerun/datatypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/datatypes/view_coordinates.py index f694e3bb5395..1c74dafbdbb7 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/view_coordinates.py @@ -35,13 +35,15 @@ class ViewCoordinates(ViewCoordinatesExt): """ **Datatype**: How we interpret the coordinate system of an entity/space. - For instance: What is "up"? What does the Z axis mean? Is this right-handed or left-handed? + For instance: What is "up"? What does the Z axis mean? The three coordinates are always ordered as [x, y, z]. For example [Right, Down, Forward] means that the X axis points to the right, the Y axis points down, and the Z axis points forward. + ⚠ [Rerun does not yet support left-handed coordinate systems](https://github.com/rerun-io/rerun/issues/5032). + The following constants are used to represent the different directions: * Up = 1 * Down = 2 diff --git a/scripts/generate_view_coordinate_defs.py b/scripts/generate_view_coordinate_defs.py index 1a8fd3d34b4e..078afa788bea 100755 --- a/scripts/generate_view_coordinate_defs.py +++ b/scripts/generate_view_coordinate_defs.py @@ -31,9 +31,47 @@ class ViewCoordinates: z: str -def docstring(coords: ViewCoordinates) -> str: - # TODO(emilk): warn about left-handed coordinate systems - return f"X={coords.x}, Y={coords.y}, Z={coords.z}" +def is_left_handed(coords: ViewCoordinates) -> bool: + def rfd(dir: str) -> tuple[int, int, int]: + if dir == "Right": + return (1, 0, 0) + elif dir == "Left": + return (-1, 0, 0) + elif dir == "Up": + return (0, -1, 0) + elif dir == "Down": + return (0, 1, 0) + elif dir == "Back": + return (0, 0, -1) + elif dir == "Forward": + return (0, 0, 1) + else: + raise RuntimeWarning(f"Unknown direction: {dir}") + + m00, m01, m02 = rfd(coords.x) + m10, m11, m12 = rfd(coords.y) + m20, m21, m22 = rfd(coords.z) + + deterimnant = ( + m00 * m11 * m22 + m01 * m12 * m20 + m02 * m10 * m21 - m02 * m11 * m20 - m01 * m10 * m22 - m00 * m12 * m21 + ) + + if deterimnant == 1: + return False + elif deterimnant == -1: + return True + else: + raise RuntimeWarning(f"Degenerate coordinate system: {coords} with ddeterimnant {deterimnant}") + + +def doclines(coords: ViewCoordinates) -> list[str]: + docs = [f"X={coords.x}, Y={coords.y}, Z={coords.z}"] + if is_left_handed(coords): + docs.append("") + docs.append( + "⚠️ This is a left-handed coordinate system, which is [not yet supported by Rerun](https://github.com/rerun-io/rerun/issues/5032)." + ) + return docs def generate_view_permutations() -> Iterable[ViewCoordinates]: @@ -71,7 +109,8 @@ def generate_up_handed_permutations() -> Iterable[ViewCoordinates]: def rust_arch_decl(coords: ViewCoordinates) -> str: - return f'define_coordinates!("{docstring(coords)}", {coords.name} => ({coords.x}, {coords.y}, {coords.z}));\n' + docstring = "\n".join(doclines(coords)) + return f'define_coordinates!("{docstring}", {coords.name} => ({coords.x}, {coords.y}, {coords.z}));\n' def gen_rust_arch_decl() -> list[str]: @@ -91,7 +130,8 @@ def gen_rust_arch_decl() -> list[str]: def rust_cmp_decl(coords: ViewCoordinates) -> str: - return f'define_coordinates!("{docstring(coords)}", {coords.name} => ({coords.x}, {coords.y}, {coords.z}));\n' + docstring = "\n".join(doclines(coords)) + return f'define_coordinates!("{docstring}", {coords.name} => ({coords.x}, {coords.y}, {coords.z}));\n' def gen_rust_cmp_decl() -> list[str]: @@ -151,7 +191,8 @@ def gen_py_arch_def() -> list[str]: def py_cmp_decl(coords: ViewCoordinates) -> str: - return f'{coords.name}: ViewCoordinates = None # type: ignore[assignment]\n """{docstring(coords)}"""\n\n' + docstring = "\n".join(doclines(coords)) + return f'{coords.name}: ViewCoordinates = None # type: ignore[assignment]\n """{docstring}"""\n\n' def gen_py_cmp_decl() -> list[str]: @@ -189,9 +230,8 @@ def gen_py_cmp_def() -> list[str]: def cpp_arch_decl(coords: ViewCoordinates) -> str: - return ( - f"/// {docstring(coords)}\nRERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates {coords.name};\n\n" - ) + docstring = "".join(f"/// {docline}\n" for docline in doclines(coords)) + return f"{docstring}RERUN_SDK_EXPORT static const rerun::archetypes::ViewCoordinates {coords.name};\n\n" def gen_cpp_arch_decl() -> list[str]: @@ -232,9 +272,8 @@ def gen_cpp_arch_def() -> list[str]: def cpp_cmp_decl(coords: ViewCoordinates) -> str: - return ( - f"/// {docstring(coords)}\nRERUN_SDK_EXPORT static const rerun::components::ViewCoordinates {coords.name};\n\n" - ) + docstring = "".join(f"/// {docline}\n" for docline in doclines(coords)) + return f"{docstring}RERUN_SDK_EXPORT static const rerun::components::ViewCoordinates {coords.name};\n\n" def gen_cpp_cmp_decl() -> list[str]: From c23bbed6534d7013c10837fa1c43ecdccc801163 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 11 Oct 2024 14:59:12 +0200 Subject: [PATCH 08/33] Empty column tracker and new dataframe APIs on top (#7677) Before: ![image](https://github.com/user-attachments/assets/1acdb4e6-1b48-4932-89a6-cd00814726eb) After: ![image](https://github.com/user-attachments/assets/d6b13b60-9d61-4aab-b577-381d22791e26) Of course with static data this still looks pretty weird in many cases, such as shown in this screenshot, But that's a job for the upcoming https://github.com/rerun-io/rerun/issues/7668. --- * Fixes #7615 --- crates/store/re_chunk/src/util.rs | 22 ++ crates/store/re_chunk_store/src/dataframe.rs | 276 ++++++++++-------- crates/store/re_chunk_store/src/gc.rs | 1 + crates/store/re_chunk_store/src/lib.rs | 4 +- crates/store/re_chunk_store/src/store.rs | 66 +++++ crates/store/re_chunk_store/src/writes.rs | 20 +- crates/store/re_dataframe/src/engine.rs | 21 +- crates/store/re_dataframe/src/query.rs | 11 +- .../src/space_view_class.rs | 15 +- rerun_py/src/dataframe.rs | 3 + 10 files changed, 284 insertions(+), 155 deletions(-) diff --git a/crates/store/re_chunk/src/util.rs b/crates/store/re_chunk/src/util.rs index 821397f7d79b..30ed831529bb 100644 --- a/crates/store/re_chunk/src/util.rs +++ b/crates/store/re_chunk/src/util.rs @@ -12,6 +12,28 @@ use itertools::Itertools; // --- +/// Returns true if the given `list_array` is semantically empty. +/// +/// Semantic emptiness is defined as either one of these: +/// * The list is physically empty (literally no data). +/// * The list only contains null entries, or empty arrays, or a mix of both. +pub fn is_list_array_semantically_empty(list_array: &ArrowListArray) -> bool { + let is_physically_empty = || list_array.is_empty(); + + let is_all_nulls = || { + list_array + .validity() + .map_or(false, |bitmap| bitmap.unset_bits() == list_array.len()) + }; + + let is_all_empties = || list_array.offsets().lengths().all(|len| len == 0); + + let is_a_mix_of_nulls_and_empties = + || list_array.iter().flatten().all(|array| array.is_empty()); + + is_physically_empty() || is_all_nulls() || is_all_empties() || is_a_mix_of_nulls_and_empties() +} + /// Create a sparse list-array out of an array of arrays. /// /// All arrays must have the same datatype. diff --git a/crates/store/re_chunk_store/src/dataframe.rs b/crates/store/re_chunk_store/src/dataframe.rs index 42c9d23c7eac..10433e05e1af 100644 --- a/crates/store/re_chunk_store/src/dataframe.rs +++ b/crates/store/re_chunk_store/src/dataframe.rs @@ -6,17 +6,12 @@ use arrow2::{ array::ListArray as ArrowListArray, datatypes::{DataType as ArrowDatatype, Field as ArrowField}, }; -use nohash_hasher::IntSet; use re_chunk::TimelineName; use re_log_types::{EntityPath, ResolvedTimeRange, TimeInt, Timeline}; use re_types_core::{ArchetypeName, ComponentName}; -use crate::ChunkStore; - -// Used all over in docstrings. -#[allow(unused_imports)] -use crate::RowId; +use crate::{ChunkStore, ColumnMetadata}; // --- Descriptors --- @@ -196,6 +191,17 @@ pub struct ComponentColumnDescriptor { /// Whether this column represents static data. pub is_static: bool, + + /// Whether this column represents an indicator component. + pub is_indicator: bool, + + /// Whether this column represents a [`Clear`]-related components. + /// + /// [`Clear`]: re_types_core::archetypes::Clear + pub is_tombstone: bool, + + /// Whether this column contains either no data or only contains null and/or empty values (`[]`). + pub is_semantically_empty: bool, } impl PartialOrd for ComponentColumnDescriptor { @@ -216,6 +222,9 @@ impl Ord for ComponentColumnDescriptor { join_encoding: _, store_datatype: _, is_static: _, + is_indicator: _, + is_tombstone: _, + is_semantically_empty: _, } = self; entity_path @@ -236,6 +245,9 @@ impl std::fmt::Display for ComponentColumnDescriptor { join_encoding: _, store_datatype: _, is_static, + is_indicator: _, + is_tombstone: _, + is_semantically_empty: _, } = self; let s = match (archetype_name, component_name, archetype_field_name) { @@ -265,26 +277,6 @@ impl std::fmt::Display for ComponentColumnDescriptor { } impl ComponentColumnDescriptor { - #[inline] - pub fn new(entity_path: EntityPath) -> Self { - let join_encoding = JoinEncoding::default(); - - // NOTE: The data is always a at least a list, whether it's latest-at or range. - // It might be wrapped further in e.g. a dict, but at the very least - // it's a list. - let store_datatype = ArrowListArray::::default_datatype(C::arrow_datatype()); - - Self { - entity_path, - archetype_name: None, - archetype_field_name: None, - component_name: C::name(), - join_encoding, - store_datatype, - is_static: false, - } - } - #[inline] pub fn matches(&self, entity_path: &EntityPath, component_name: &ComponentName) -> bool { &self.entity_path == entity_path && &self.component_name == component_name @@ -299,10 +291,17 @@ impl ComponentColumnDescriptor { join_encoding: _, store_datatype: _, is_static, + is_indicator, + is_tombstone, + is_semantically_empty, } = self; [ (*is_static).then_some(("sorbet.is_static".to_owned(), "yes".to_owned())), + (*is_indicator).then_some(("sorbet.is_indicator".to_owned(), "yes".to_owned())), + (*is_tombstone).then_some(("sorbet.is_tombstone".to_owned(), "yes".to_owned())), + (*is_semantically_empty) + .then_some(("sorbet.is_semantically_empty".to_owned(), "yes".to_owned())), Some(("sorbet.path".to_owned(), entity_path.to_string())), Some(( "sorbet.semantic_type".to_owned(), @@ -592,6 +591,28 @@ pub struct QueryExpression { /// ``` pub view_contents: Option, + /// Whether the `view_contents` should ignore semantically empty columns. + /// + /// A semantically empty column is a column that either contains no data at all, or where all + /// values are either nulls or empty arrays (`[]`). + /// + /// `view_contents`: [`QueryExpression::view_contents`] + pub include_semantically_empty_columns: bool, + + /// Whether the `view_contents` should ignore columns corresponding to indicator components. + /// + /// Indicator components are marker components, generally automatically inserted by Rerun, that + /// helps keep track of the original context in which a piece of data was logged/sent. + /// + /// `view_contents`: [`QueryExpression::view_contents`] + pub include_indicator_columns: bool, + + /// Whether the `view_contents` should ignore columns corresponding to `Clear`-related components. + /// + /// `view_contents`: [`QueryExpression::view_contents`] + /// `Clear`: [`re_types_core::archetypes::Clear`] + pub include_tombstone_columns: bool, + /// The index used to filter out _rows_ from the view contents. /// /// Only rows where at least 1 column contains non-null data at that index will be kept in the @@ -670,6 +691,9 @@ impl QueryExpression { Self { view_contents: None, + include_semantically_empty_columns: false, + include_indicator_columns: false, + include_tombstone_columns: false, filtered_index: index, filtered_index_range: None, filtered_index_values: None, @@ -690,9 +714,8 @@ impl ChunkStore { /// entity that has been written to the store so far. /// /// The order of the columns is guaranteed to be in a specific order: - /// * first, the control columns in lexical order (`RowId`); - /// * second, the time columns in lexical order (`frame_nr`, `log_time`, ...); - /// * third, the component columns in lexical order (`Color`, `Radius, ...`). + /// * first, the time columns in lexical order (`frame_nr`, `log_time`, ...); + /// * second, the component columns in lexical order (`Color`, `Radius, ...`). pub fn schema(&self) -> Vec { re_tracing::profile_function!(); @@ -703,88 +726,47 @@ impl ChunkStore { }) }); - let static_components = - self.static_chunk_ids_per_entity - .iter() - .flat_map(|(entity_path, per_component)| { - // TODO(#6889): Fill `archetype_name`/`archetype_field_name` (or whatever their - // final name ends up being) once we generate tags. - per_component.keys().filter_map(|component_name| { - self.lookup_datatype(component_name).map(|datatype| { - ColumnDescriptor::Component(ComponentColumnDescriptor { - entity_path: entity_path.clone(), - archetype_name: None, - archetype_field_name: None, - component_name: *component_name, - store_datatype: ArrowListArray::::default_datatype( - datatype.clone(), - ), - join_encoding: JoinEncoding::default(), - is_static: true, - }) - }) - }) - }); - - // TODO(cmc): Opportunities for parallelization, if it proves to be a net positive in practice. - let temporal_components = self - .temporal_chunk_ids_per_entity_per_component + let components = self + .per_column_metadata .iter() - .flat_map(|(entity_path, per_timeline)| { - per_timeline - .iter() - .map(move |(timeline, per_component)| (entity_path, timeline, per_component)) + .flat_map(|(entity_path, per_component)| { + per_component + .keys() + .map(move |component_name| (entity_path, component_name)) }) - .flat_map(|(entity_path, _timeline, per_component)| { + .filter_map(|(entity_path, component_name)| { + let metadata = self.lookup_column_metadata(entity_path, component_name)?; + let datatype = self.lookup_datatype(component_name)?; + + Some(((entity_path, component_name), (metadata, datatype))) + }) + .map(|((entity_path, component_name), (metadata, datatype))| { + let ColumnMetadata { + is_static, + is_indicator, + is_tombstone, + is_semantically_empty, + } = metadata; + // TODO(#6889): Fill `archetype_name`/`archetype_field_name` (or whatever their // final name ends up being) once we generate tags. - per_component.keys().filter_map(|component_name| { - self.lookup_datatype(component_name).map(|datatype| { - ColumnDescriptor::Component(ComponentColumnDescriptor { - entity_path: entity_path.clone(), - archetype_name: None, - archetype_field_name: None, - component_name: *component_name, - // NOTE: The data is always a at least a list, whether it's latest-at or range. - // It might be wrapped further in e.g. a dict, but at the very least - // it's a list. - store_datatype: ArrowListArray::::default_datatype( - datatype.clone(), - ), - join_encoding: JoinEncoding::default(), - // NOTE: This will make it so shadowed temporal data automatically gets - // discarded from the schema. - is_static: self - .static_chunk_ids_per_entity - .get(entity_path) - .map_or(false, |per_component| { - per_component.contains_key(component_name) - }), - }) - }) + ColumnDescriptor::Component(ComponentColumnDescriptor { + entity_path: entity_path.clone(), + archetype_name: None, + archetype_field_name: None, + component_name: *component_name, + // NOTE: The data is always a at least a list, whether it's latest-at or range. + // It might be wrapped further in e.g. a dict, but at the very least + // it's a list. + store_datatype: ArrowListArray::::default_datatype(datatype.clone()), + join_encoding: JoinEncoding::default(), + is_static, + is_indicator, + is_tombstone, + is_semantically_empty, }) }); - use re_types_core::Archetype as _; - let clear_related_components: IntSet = - re_types_core::archetypes::Clear::all_components() - .iter() - .copied() - .collect(); - - let components = static_components - .chain(temporal_components) - .filter(|col| match col { - ColumnDescriptor::Time(_) => true, - ColumnDescriptor::Component(descr) => { - let is_indicator = descr.component_name.is_indicator_component(); - // Tombstones are not exposed to end users -- only their _effect_. - let is_tombstone = clear_related_components.contains(&descr.component_name); - !is_indicator && !is_tombstone - } - }) - .collect::>(); - timelines.chain(components).collect() } @@ -811,20 +793,25 @@ impl ChunkStore { &self, selector: &ComponentColumnSelector, ) -> ComponentColumnDescriptor { + let ColumnMetadata { + is_static, + is_indicator, + is_tombstone, + is_semantically_empty, + } = self + .lookup_column_metadata(&selector.entity_path, &selector.component) + .unwrap_or(ColumnMetadata { + is_static: false, + is_indicator: false, + is_tombstone: false, + is_semantically_empty: false, + }); + let datatype = self .lookup_datatype(&selector.component) .cloned() .unwrap_or_else(|| ArrowDatatype::Null); - let is_static = self - .static_chunk_ids_per_entity - .get(&selector.entity_path) - .map_or(false, |per_component| { - per_component.contains_key(&selector.component) - }); - - // TODO(#6889): Fill `archetype_name`/`archetype_field_name` (or whatever their - // final name ends up being) once we generate tags. ComponentColumnDescriptor { entity_path: selector.entity_path.clone(), archetype_name: None, @@ -833,6 +820,9 @@ impl ChunkStore { store_datatype: ArrowListArray::::default_datatype(datatype.clone()), join_encoding: selector.join_encoding, is_static, + is_indicator, + is_tombstone, + is_semantically_empty, } } @@ -859,29 +849,59 @@ impl ChunkStore { .collect() } - /// Returns the filtered schema for the given [`ViewContentsSelector`]. + /// Returns the filtered schema for the given [`QueryExpression`]. /// /// The order of the columns is guaranteed to be in a specific order: - /// * first, the control columns in lexical order (`RowId`); - /// * second, the time columns in lexical order (`frame_nr`, `log_time`, ...); - /// * third, the component columns in lexical order (`Color`, `Radius, ...`). - pub fn schema_for_view_contents( - &self, - view_contents: &ViewContentsSelector, - ) -> Vec { + /// * first, the time columns in lexical order (`frame_nr`, `log_time`, ...); + /// * second, the component columns in lexical order (`Color`, `Radius, ...`). + pub fn schema_for_query(&self, query: &QueryExpression) -> Vec { re_tracing::profile_function!(); + let QueryExpression { + view_contents, + include_semantically_empty_columns, + include_indicator_columns, + include_tombstone_columns, + filtered_index: _, + filtered_index_range: _, + filtered_index_values: _, + using_index_values: _, + filtered_point_of_view: _, + sparse_fill_strategy: _, + selection: _, + } = query; + + let filter = |column: &ComponentColumnDescriptor| { + let is_part_of_view_contents = || { + view_contents.as_ref().map_or(true, |view_contents| { + view_contents + .get(&column.entity_path) + .map_or(false, |components| { + components.as_ref().map_or(true, |components| { + components.contains(&column.component_name) + }) + }) + }) + }; + + let passes_semantically_empty_check = + || *include_semantically_empty_columns || !column.is_semantically_empty; + + let passes_indicator_check = || *include_indicator_columns || !column.is_indicator; + + let passes_tombstone_check = || *include_tombstone_columns || !column.is_tombstone; + + is_part_of_view_contents() + && passes_semantically_empty_check() + && passes_indicator_check() + && passes_tombstone_check() + }; + self.schema() .into_iter() .filter(|column| match column { ColumnDescriptor::Time(_) => true, - ColumnDescriptor::Component(column) => view_contents - .get(&column.entity_path) - .map_or(false, |components| { - components.as_ref().map_or(true, |components| { - components.contains(&column.component_name) - }) - }), + ColumnDescriptor::Component(column) => filter(column), }) .collect() } diff --git a/crates/store/re_chunk_store/src/gc.rs b/crates/store/re_chunk_store/src/gc.rs index 2cf7baddb927..67035ebdc12e 100644 --- a/crates/store/re_chunk_store/src/gc.rs +++ b/crates/store/re_chunk_store/src/gc.rs @@ -340,6 +340,7 @@ impl ChunkStore { info: _, config: _, type_registry: _, + per_column_metadata: _, // column metadata is additive only chunks_per_chunk_id, chunk_ids_per_min_row_id, temporal_chunk_ids_per_entity_per_component, diff --git a/crates/store/re_chunk_store/src/lib.rs b/crates/store/re_chunk_store/src/lib.rs index 9d54d3df28a2..8deb7e52f2be 100644 --- a/crates/store/re_chunk_store/src/lib.rs +++ b/crates/store/re_chunk_store/src/lib.rs @@ -32,9 +32,11 @@ pub use self::dataframe::{ pub use self::events::{ChunkStoreDiff, ChunkStoreDiffKind, ChunkStoreEvent}; pub use self::gc::{GarbageCollectionOptions, GarbageCollectionTarget}; pub use self::stats::{ChunkStoreChunkStats, ChunkStoreStats}; -pub use self::store::{ChunkStore, ChunkStoreConfig, ChunkStoreGeneration}; +pub use self::store::{ChunkStore, ChunkStoreConfig, ChunkStoreGeneration, ColumnMetadata}; pub use self::subscribers::{ChunkStoreSubscriber, ChunkStoreSubscriberHandle}; +pub(crate) use self::store::ColumnMetadataState; + // Re-exports #[doc(no_inline)] pub use re_chunk::{ diff --git a/crates/store/re_chunk_store/src/store.rs b/crates/store/re_chunk_store/src/store.rs index b95af5d4fa62..28d825aa9af3 100644 --- a/crates/store/re_chunk_store/src/store.rs +++ b/crates/store/re_chunk_store/src/store.rs @@ -276,6 +276,33 @@ pub type ChunkIdSetPerTimePerTimelinePerEntity = BTreeMap, + pub(crate) per_column_metadata: IntMap>, + pub(crate) chunks_per_chunk_id: BTreeMap>, /// All [`ChunkId`]s currently in the store, indexed by the smallest [`RowId`] in each of them. @@ -370,6 +399,7 @@ impl Clone for ChunkStore { info: self.info.clone(), config: self.config.clone(), type_registry: self.type_registry.clone(), + per_column_metadata: self.per_column_metadata.clone(), chunks_per_chunk_id: self.chunks_per_chunk_id.clone(), chunk_ids_per_min_row_id: self.chunk_ids_per_min_row_id.clone(), temporal_chunk_ids_per_entity_per_component: self @@ -394,6 +424,7 @@ impl std::fmt::Display for ChunkStore { info: _, config, type_registry: _, + per_column_metadata: _, chunks_per_chunk_id, chunk_ids_per_min_row_id: chunk_id_per_min_row_id, temporal_chunk_ids_per_entity_per_component: _, @@ -449,6 +480,7 @@ impl ChunkStore { info: None, config, type_registry: Default::default(), + per_column_metadata: Default::default(), chunk_ids_per_min_row_id: Default::default(), chunks_per_chunk_id: Default::default(), temporal_chunk_ids_per_entity_per_component: Default::default(), @@ -517,6 +549,40 @@ impl ChunkStore { pub fn lookup_datatype(&self, component_name: &ComponentName) -> Option<&ArrowDataType> { self.type_registry.get(component_name) } + + /// Lookup the [`ColumnMetadata`] for a specific [`EntityPath`] and [`re_types_core::Component`]. + pub fn lookup_column_metadata( + &self, + entity_path: &EntityPath, + component_name: &ComponentName, + ) -> Option { + let ColumnMetadataState { + is_semantically_empty, + } = self + .per_column_metadata + .get(entity_path) + .and_then(|per_component| per_component.get(component_name))?; + + let is_static = self + .static_chunk_ids_per_entity + .get(entity_path) + .map_or(false, |per_component| { + per_component.get(component_name).is_some() + }); + + let is_indicator = component_name.is_indicator_component(); + + use re_types_core::Archetype as _; + let is_tombstone = + re_types_core::archetypes::Clear::all_components().contains(component_name); + + Some(ColumnMetadata { + is_static, + is_indicator, + is_tombstone, + is_semantically_empty: *is_semantically_empty, + }) + } } // --- diff --git a/crates/store/re_chunk_store/src/writes.rs b/crates/store/re_chunk_store/src/writes.rs index 6c574dc11bdd..4b0a404726ae 100644 --- a/crates/store/re_chunk_store/src/writes.rs +++ b/crates/store/re_chunk_store/src/writes.rs @@ -9,7 +9,7 @@ use re_types_core::SizeBytes; use crate::{ store::ChunkIdSetPerTime, ChunkStore, ChunkStoreChunkStats, ChunkStoreConfig, ChunkStoreDiff, - ChunkStoreError, ChunkStoreEvent, ChunkStoreResult, + ChunkStoreError, ChunkStoreEvent, ChunkStoreResult, ColumnMetadataState, }; // Used all over in docstrings. @@ -321,6 +321,21 @@ impl ChunkStore { component_name, ArrowListArray::::get_child_type(list_array.data_type()).clone(), ); + + let column_metadata_state = self + .per_column_metadata + .entry(chunk.entity_path().clone()) + .or_default() + .entry(component_name) + .or_insert(ColumnMetadataState { + is_semantically_empty: true, + }); + { + let is_semantically_empty = + re_chunk::util::is_list_array_semantically_empty(list_array); + + column_metadata_state.is_semantically_empty &= is_semantically_empty; + } } let events = if self.config.enable_changelog { @@ -485,6 +500,7 @@ impl ChunkStore { info: _, config: _, type_registry: _, + per_column_metadata, chunks_per_chunk_id, chunk_ids_per_min_row_id, temporal_chunk_ids_per_entity_per_component, @@ -498,6 +514,8 @@ impl ChunkStore { event_id, } = self; + per_column_metadata.remove(entity_path); + let dropped_static_chunks = { let dropped_static_chunk_ids: BTreeSet<_> = static_chunk_ids_per_entity .remove(entity_path) diff --git a/crates/store/re_dataframe/src/engine.rs b/crates/store/re_dataframe/src/engine.rs index e702c7a5c578..88e4f37cc9c7 100644 --- a/crates/store/re_dataframe/src/engine.rs +++ b/crates/store/re_dataframe/src/engine.rs @@ -1,5 +1,5 @@ use re_chunk::{EntityPath, TransportChunk}; -use re_chunk_store::{ChunkStore, ColumnDescriptor, QueryExpression, ViewContentsSelector}; +use re_chunk_store::{ChunkStore, ColumnDescriptor, QueryExpression}; use re_log_types::EntityPathFilter; use re_query::Caches; @@ -41,26 +41,21 @@ impl QueryEngine<'_> { /// entity that has been written to the store so far. /// /// The order of the columns to guaranteed to be in a specific order: - /// * first, the control columns in lexical order (`RowId`); - /// * second, the time columns in lexical order (`frame_nr`, `log_time`, ...); - /// * third, the component columns in lexical order (`Color`, `Radius, ...`). + /// * first, the time columns in lexical order (`frame_nr`, `log_time`, ...); + /// * second, the component columns in lexical order (`Color`, `Radius, ...`). #[inline] pub fn schema(&self) -> Vec { self.store.schema() } - /// Returns the filtered schema for the given `view_contents`. + /// Returns the filtered schema for the given [`QueryExpression`]. /// /// The order of the columns is guaranteed to be in a specific order: - /// * first, the control columns in lexical order (`RowId`); - /// * second, the time columns in lexical order (`frame_nr`, `log_time`, ...); - /// * third, the component columns in lexical order (`Color`, `Radius, ...`). + /// * first, the time columns in lexical order (`frame_nr`, `log_time`, ...); + /// * second, the component columns in lexical order (`Color`, `Radius, ...`). #[inline] - pub fn schema_for_view_contents( - &self, - view_contents: &ViewContentsSelector, - ) -> Vec { - self.store.schema_for_view_contents(view_contents) + pub fn schema_for_query(&self, query: &QueryExpression) -> Vec { + self.store.schema_for_query(query) } /// Starts a new query by instantiating a [`QueryHandle`]. diff --git a/crates/store/re_dataframe/src/query.rs b/crates/store/re_dataframe/src/query.rs index 2abf8c7227ca..970e975de4cc 100644 --- a/crates/store/re_dataframe/src/query.rs +++ b/crates/store/re_dataframe/src/query.rs @@ -163,12 +163,8 @@ impl QueryHandle<'_> { fn init_(&self) -> QueryHandleState { re_tracing::profile_scope!("init"); - // 1. Compute the schema of the view contents. - let view_contents = if let Some(view_contents) = self.query.view_contents.as_ref() { - self.engine.store.schema_for_view_contents(view_contents) - } else { - self.engine.store.schema() - }; + // 1. Compute the schema for the query. + let view_contents = self.engine.store.schema_for_query(&self.query); // 2. Compute the schema of the selected contents. // @@ -405,6 +401,9 @@ impl QueryHandle<'_> { store_datatype: arrow2::datatypes::DataType::Null, join_encoding: JoinEncoding::default(), is_static: false, + is_indicator: false, + is_tombstone: false, + is_semantically_empty: false, }), ) }, diff --git a/crates/viewer/re_space_view_dataframe/src/space_view_class.rs b/crates/viewer/re_space_view_dataframe/src/space_view_class.rs index cecbbf0a3ef8..98178d38a619 100644 --- a/crates/viewer/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/viewer/re_space_view_dataframe/src/space_view_class.rs @@ -143,23 +143,26 @@ mode sets the default time range to _everything_. You can override this in the s SparseFillStrategy::None }; - let view_columns = query_engine.schema_for_view_contents(&view_contents); - let selected_columns = - view_query.apply_column_visibility_to_view_columns(ctx, &view_columns)?; - - let dataframe_query = re_chunk_store::QueryExpression { + let mut dataframe_query = re_chunk_store::QueryExpression { view_contents: Some(view_contents), filtered_index: view_query.timeline(ctx)?, filtered_index_range: Some(view_query.filter_by_range()?), filtered_point_of_view: view_query.filter_by_event()?, sparse_fill_strategy, - selection: selected_columns, + selection: None, // not yet unsupported by the dataframe view filtered_index_values: None, using_index_values: None, + include_semantically_empty_columns: false, + include_indicator_columns: false, + include_tombstone_columns: false, }; + let view_columns = query_engine.schema_for_query(&dataframe_query); + dataframe_query.selection = + view_query.apply_column_visibility_to_view_columns(ctx, &view_columns)?; + let query_handle = query_engine.query(dataframe_query); let hide_column_actions = diff --git a/rerun_py/src/dataframe.rs b/rerun_py/src/dataframe.rs index 76698e5b7657..6651fd2020b6 100644 --- a/rerun_py/src/dataframe.rs +++ b/rerun_py/src/dataframe.rs @@ -670,6 +670,9 @@ impl PyRecording { let query = QueryExpression { view_contents: Some(contents), + include_semantically_empty_columns: false, + include_indicator_columns: false, + include_tombstone_columns: false, filtered_index: timeline.timeline, filtered_index_range: None, filtered_index_values: None, From 9f23ae0d01c7ba4dcdd2763293946c04e4e917e8 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 11 Oct 2024 15:07:11 +0200 Subject: [PATCH 09/33] Dataframe v2: big ol' hindsight-driven refactoring (#7683) Simpler. Faster. Correct-er. * Fixes #7681 * DNM: requires #7677 --- Cargo.lock | 1 - crates/store/re_dataframe/Cargo.toml | 1 - crates/store/re_dataframe/src/query.rs | 260 ++++++------------------- 3 files changed, 63 insertions(+), 199 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cafc4d1da18f..ab71bbc4dffc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5134,7 +5134,6 @@ dependencies = [ "anyhow", "itertools 0.13.0", "nohash-hasher", - "parking_lot", "re_arrow2", "re_chunk", "re_chunk_store", diff --git a/crates/store/re_dataframe/Cargo.toml b/crates/store/re_dataframe/Cargo.toml index 144168d505a1..1370ca068596 100644 --- a/crates/store/re_dataframe/Cargo.toml +++ b/crates/store/re_dataframe/Cargo.toml @@ -38,7 +38,6 @@ anyhow.workspace = true arrow2.workspace = true itertools.workspace = true nohash-hasher.workspace = true -parking_lot.workspace = true [dev-dependencies] re_types.workspace = true diff --git a/crates/store/re_dataframe/src/query.rs b/crates/store/re_dataframe/src/query.rs index 970e975de4cc..2eb70680b956 100644 --- a/crates/store/re_dataframe/src/query.rs +++ b/crates/store/re_dataframe/src/query.rs @@ -16,7 +16,6 @@ use arrow2::{ Either, }; use itertools::Itertools; -use parking_lot::Mutex; use nohash_hasher::{IntMap, IntSet}; use re_chunk::{ @@ -111,18 +110,6 @@ struct QueryHandleState { // NOTE: Reminder: we have to query everything in the _view_, irrelevant of the current selection. view_chunks: Vec>, - /// The index in `view_chunks` where the POV chunks are stored. - /// - /// * If set to `None`, then the caller didn't request a POV at all. - /// * If set to `Some(usize::MAX)`, then a POV was requested but couldn't be found in the view. - /// * Otherwise, points to the chunks that should be used to drive the iteration. - view_pov_chunks_idx: Option, - - /// The stack of index values left to sample. - /// - /// Stored in reverse order, i.e. `pop()` is the next sample to retrieve. - using_index_values_stack: Mutex>>, - /// Tracks the current row index: the position of the iterator. For [`QueryHandle::next_row`]. /// /// This represents the number of rows that the caller has iterated on: it is completely @@ -188,19 +175,13 @@ impl QueryHandle<'_> { metadata: Default::default(), }; - let using_index_values_stack = self - .query - .using_index_values - .as_ref() - .map(|values| values.iter().rev().copied().collect_vec()); - // 4. Perform the query and keep track of all the relevant chunks. let query = { let index_range = - if let Some(using_index_values_stack) = using_index_values_stack.as_ref() { - using_index_values_stack - .last() // reminder: it's reversed (stack) - .and_then(|start| using_index_values_stack.first().map(|end| (start, end))) + if let Some(using_index_values) = self.query.using_index_values.as_ref() { + using_index_values + .first() + .and_then(|start| using_index_values.last().map(|end| (start, end))) .map_or(ResolvedTimeRange::EMPTY, |(start, end)| { ResolvedTimeRange::new(*start, *end) }) @@ -279,10 +260,8 @@ impl QueryHandle<'_> { // // Used to achieve ~O(log(n)) pagination. let unique_index_values = - if let Some(using_index_values_stack) = using_index_values_stack.as_ref() { - let mut all_unique_index_values = using_index_values_stack.clone(); - all_unique_index_values.sort(); - all_unique_index_values + if let Some(using_index_values) = self.query.using_index_values.as_ref() { + using_index_values.iter().copied().collect_vec() } else { re_tracing::profile_scope!("index_values"); @@ -321,8 +300,6 @@ impl QueryHandle<'_> { selected_contents, arrow_schema, view_chunks, - view_pov_chunks_idx, - using_index_values_stack: Mutex::new(using_index_values_stack), cur_row: AtomicU64::new(0), unique_index_values, } @@ -606,6 +583,7 @@ impl QueryHandle<'_> { } /// The query used to instantiate this handle. + #[inline] pub fn query(&self) -> &QueryExpression { &self.query } @@ -613,6 +591,7 @@ impl QueryHandle<'_> { /// Describes the columns that make up this view. /// /// See [`QueryExpression::view_contents`]. + #[inline] pub fn view_contents(&self) -> &[ColumnDescriptor] { &self.init().view_contents } @@ -622,6 +601,7 @@ impl QueryHandle<'_> { /// The extra `usize` is the index in [`Self::view_contents`] that this selection points to. /// /// See [`QueryExpression::selection`]. + #[inline] pub fn selected_contents(&self) -> &[(usize, ColumnDescriptor)] { &self.init().selected_contents } @@ -629,6 +609,7 @@ impl QueryHandle<'_> { /// All results returned by this handle will strictly follow this Arrow schema. /// /// Columns that do not yield any data will still be present in the results, filled with null values. + #[inline] pub fn schema(&self) -> &ArrowSchema { &self.init().arrow_schema } @@ -651,10 +632,13 @@ impl QueryHandle<'_> { /// I.e.: it's pretty cheap already. #[inline] pub fn seek_to_row(&self, row_idx: usize) { - let Some(index_value) = self.init().unique_index_values.get(row_idx) else { + let state = self.init(); + + let Some(index_value) = state.unique_index_values.get(row_idx) else { return; }; + state.cur_row.store(row_idx as _, Ordering::Relaxed); self.seek_to_index_value(*index_value); } @@ -675,25 +659,11 @@ impl QueryHandle<'_> { /// the chunk's time range contains the `index_value`. /// /// I.e.: it's pretty cheap already. - pub fn seek_to_index_value(&self, index_value: IndexValue) { + fn seek_to_index_value(&self, index_value: IndexValue) { re_tracing::profile_function!(); let state = self.init(); - // NOTE: If there are explicit samples specified, then we need to make sure to properly reset - // them each time an arbitrary seek happens. - let mut using_index_values_stack = state.using_index_values_stack.lock(); - if using_index_values_stack.is_some() { - let mut index_values = state - .unique_index_values - .iter() - .filter(|&&v| v >= index_value) - .copied() - .collect_vec(); - index_values.reverse(); - *using_index_values_stack = Some(index_values); - } - if index_value.is_static() { for chunks in &state.view_chunks { for (cursor, _chunk) in chunks { @@ -763,7 +733,7 @@ impl QueryHandle<'_> { /// /// ## Pagination /// - /// Use [`Self::seek_to_row`] and [`Self::seek_to_index_value`]: + /// Use [`Self::seek_to_row`]: /// ```ignore /// query_handle.seek_to_row(42); /// for row in query_handle.into_iter().take(len) { @@ -782,9 +752,6 @@ impl QueryHandle<'_> { /// How far are we into this `Chunk`? cursor: u64, - /// What's the index value at the current cursor? - index_value: TimeInt, - /// What's the `RowId` at the current cursor? row_id: RowId, } @@ -805,7 +772,8 @@ impl QueryHandle<'_> { let state = self.init(); - let _cur_row = state.cur_row.fetch_add(1, Ordering::Relaxed); + let row_idx = state.cur_row.fetch_add(1, Ordering::Relaxed); + let cur_index_value = state.unique_index_values.get(row_idx as usize)?; // First, we need to find, among all the chunks available for the current view contents, // what is their index value for the current row? @@ -821,141 +789,65 @@ impl QueryHandle<'_> { for (view_column_idx, view_chunks) in state.view_chunks.iter().enumerate() { let streaming_state = &mut view_streaming_state[view_column_idx]; - for (cur_cursor, cur_chunk) in view_chunks { - // NOTE: Too soon to increment the cursor, we cannot know yet which chunks will or - // will not be part of the current row. - let cur_cursor_value = cur_cursor.load(Ordering::Relaxed); - + 'overlaps: for (cur_cursor, cur_chunk) in view_chunks { // TODO(cmc): This can easily be optimized by looking ahead and breaking as soon as chunks // stop overlapping. - let Some((cur_index_value, cur_row_id)) = cur_chunk + // NOTE: Too soon to increment the cursor, we cannot know yet which chunks will or + // will not be part of the current row. + let mut cur_cursor_value = cur_cursor.load(Ordering::Relaxed); + + // TODO(cmc): make this a tiny bit smarter so we can remove the need for + // deduped_latest_on_index, which would be very welcome right now given we don't + // have an Arrow ListView at our disposal. + let cur_indices = cur_chunk .iter_indices(&self.query.filtered_index) - .nth(cur_cursor_value as _) - else { - continue; + .collect_vec(); + let (index_value, cur_row_id) = 'walk: loop { + let Some((index_value, cur_row_id)) = + cur_indices.get(cur_cursor_value as usize).copied() + else { + continue 'overlaps; + }; + + if index_value == *cur_index_value { + break 'walk (index_value, cur_row_id); + } + + if index_value > *cur_index_value { + continue 'overlaps; + } + + cur_cursor_value = cur_cursor.fetch_add(1, Ordering::Relaxed) + 1; }; + debug_assert_eq!(index_value, *cur_index_value); + if let Some(streaming_state) = streaming_state.as_mut() { let StreamingJoinStateEntry { chunk, cursor, - index_value, row_id, } = streaming_state; - let cur_chunk_has_smaller_index_value = cur_index_value < *index_value; - // If these two chunks overlap and share the index value of the current - // iteration, we shall pick the row with the most recent row-id. - let cur_chunk_has_equal_index_but_higher_rowid = - cur_index_value == *index_value && cur_row_id > *row_id; - - if cur_chunk_has_smaller_index_value - || cur_chunk_has_equal_index_but_higher_rowid - { + if cur_row_id > *row_id { *chunk = cur_chunk; *cursor = cur_cursor_value; - *index_value = cur_index_value; *row_id = cur_row_id; } } else { *streaming_state = Some(StreamingJoinStateEntry { chunk: cur_chunk, cursor: cur_cursor_value, - index_value: cur_index_value, row_id: cur_row_id, }); }; } } - // What's the index value we're looking for at the current iteration? - // - // `None` if we ran out of chunks. - let mut cur_index_value = if let Some(view_pov_chunks_idx) = state.view_pov_chunks_idx { - // If we do have a set point-of-view, then the current iteration corresponds to the - // next available index value across all PoV chunks. - view_streaming_state - .get(view_pov_chunks_idx) - .and_then(|streaming_state| streaming_state.as_ref().map(|s| s.index_value)) - } else { - // If we do not have a set point-of-view, then the current iteration corresponds to the - // smallest available index value across all available chunks. - view_streaming_state - .iter() - .flatten() - // NOTE: We're purposefully ignoring RowId-related semantics here: we just want to know - // the value we're looking for on the "main" index (dedupe semantics). - .min_by_key(|streaming_state| streaming_state.index_value) - .map(|streaming_state| streaming_state.index_value) - }; - - // What's the next sample we're interested in, if any? - // - // `None` iff the query isn't sampled. Short-circuits if the query is sampled but has run out of samples. - let sampled_index_value = - if let Some(using_index_values) = state.using_index_values_stack.lock().as_mut() { - // NOTE: Look closely -- this short-circuits is there are no more samples in the vec. - Some(using_index_values.last().copied()?) - } else { - None - }; - - if let Some(sampled_index_value) = sampled_index_value { - if let Some(cur_index_value) = cur_index_value { - // If the current natural index value is smaller than the next sampled index value, then we need - // to skip the current row. - if sampled_index_value > cur_index_value { - self.increment_cursors_at_index_value(cur_index_value); - return self.next_row(); - } - } - - // If the current natural index value is equal to the current sample, then we should - // return the current row as usual. - // - // If the current natural index value is greater than the current sample, or if we wan out of - // natural indices altogether, then we should return whatever data is available for the - // current row (which might be all 'nulls'). - // - // Either way, we can pop the sample from the stack, and use that as index value. - - // These unwraps cannot fail since we the only way to get here is for `state.using_index_values` - // to exist and be non-empty. - #[allow(clippy::unwrap_used)] - { - cur_index_value = Some( - state - .using_index_values_stack - .lock() - .as_mut() - .unwrap() - .pop() - .unwrap(), - ); - } - } - - let cur_index_value = cur_index_value?; - - // `filtered_index_values` & `using_index_values` are exclusive. - if sampled_index_value.is_none() { - if let Some(filtered_index_values) = self.query.filtered_index_values.as_ref() { - if !filtered_index_values.contains(&cur_index_value) { - self.increment_cursors_at_index_value(cur_index_value); - return self.next_row(); - } - } - } - let mut view_streaming_state = view_streaming_state .into_iter() - .map(|streaming_state| match streaming_state { - Some(s) if s.index_value == cur_index_value => { - Some(StreamingJoinState::StreamingJoinState(s)) - } - _ => None, - }) + .map(|streaming_state| streaming_state.map(StreamingJoinState::StreamingJoinState)) .collect_vec(); match self.query.sparse_fill_strategy { @@ -987,7 +879,7 @@ impl QueryHandle<'_> { // consecutive nulls etc). Later. let query = - re_chunk::LatestAtQuery::new(self.query.filtered_index, cur_index_value); + re_chunk::LatestAtQuery::new(self.query.filtered_index, *cur_index_value); let results = self.engine.cache.latest_at( self.engine.store, @@ -1063,20 +955,18 @@ impl QueryHandle<'_> { .or_insert((time, time_sliced)); }); - if let Some(sampled_index_value) = sampled_index_value { - if !sampled_index_value.is_static() { - // The sampled index value (if temporal) should be the one returned for the - // queried index, no matter what. - max_value_per_index.insert( - self.query.filtered_index, - ( - sampled_index_value, - ArrowPrimitiveArray::::from_vec(vec![cur_index_value.as_i64()]) - .to(self.query.filtered_index.datatype()) - .to_boxed(), - ), - ); - } + if !cur_index_value.is_static() { + // The current index value (if temporal) should be the one returned for the + // queried index, no matter what. + max_value_per_index.insert( + self.query.filtered_index, + ( + *cur_index_value, + ArrowPrimitiveArray::::from_vec(vec![cur_index_value.as_i64()]) + .to(self.query.filtered_index.datatype()) + .to_boxed(), + ), + ); } } @@ -1147,8 +1037,6 @@ impl QueryHandle<'_> { }) .collect_vec(); - self.increment_cursors_at_index_value(cur_index_value); - debug_assert_eq!(state.arrow_schema.fields.len(), selected_arrays.len()); Some(selected_arrays) @@ -1167,28 +1055,6 @@ impl QueryHandle<'_> { data: ArrowChunk::new(self.next_row()?), }) } - - /// Increment cursors for iteration corresponding to `cur_index_value`. - // - // NOTE: This is trickier than it looks: cursors need to be incremented not only for chunks - // that were used to return data during the current iteration, but also chunks that - // _attempted_ to return data and were preempted for one reason or another (overlap, - // intra-timestamp tie-break, etc). - fn increment_cursors_at_index_value(&self, cur_index_value: IndexValue) { - let state = self.init(); - for view_chunks in &state.view_chunks { - for (cur_cursor, cur_chunk) in view_chunks { - if let Some((index_value, _row_id)) = cur_chunk - .iter_indices(&self.query.filtered_index) - .nth(cur_cursor.load(Ordering::Relaxed) as _) - { - if cur_index_value == index_value { - cur_cursor.fetch_add(1, Ordering::Relaxed); - } - }; - } - } - } } impl<'a> QueryHandle<'a> { @@ -1683,10 +1549,10 @@ mod tests { "\ [ Int64[30, 40, 50, 70], - Timestamp(Nanosecond, None)[None, None, None, None], + Timestamp(Nanosecond, None)[None, None, 1970-01-01 00:00:00.000000050, 1970-01-01 00:00:00.000000070], ListArray[[2], [3], [4], [6]], ListArray[None, None, None, None], - ListArray[None, None, None, None], + ListArray[[{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 8, y: 8}]], ]\ ", ); From b69be17260ceac898e249bc8c9d3bc1b39b5fef1 Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 11 Oct 2024 09:40:31 -0400 Subject: [PATCH 10/33] rerun_py.dataframe: Add APIs for `using_index_values`, `fill_latest_at`, and `filter_is_not_null` (#7680) ### What - Resolves: https://github.com/rerun-io/rerun/issues/7455 - DNM: requires #7683 ### TODO - [x] The unit test currently fails with what looks like a bug ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7680?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7680?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7680) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Clement Rey --- rerun_py/rerun_bindings/rerun_bindings.pyi | 30 ++++++++++++ rerun_py/src/dataframe.rs | 34 ++++++++++++++ rerun_py/tests/unit/test_dataframe.py | 54 ++++++++++++++++++++++ 3 files changed, 118 insertions(+) diff --git a/rerun_py/rerun_bindings/rerun_bindings.pyi b/rerun_py/rerun_bindings/rerun_bindings.pyi index 72dcdb44801a..9ebf12f9bdb4 100644 --- a/rerun_py/rerun_bindings/rerun_bindings.pyi +++ b/rerun_py/rerun_bindings/rerun_bindings.pyi @@ -61,12 +61,42 @@ class RecordingView: """ Filter the view to only include data at the given index values. + The index values returned will be the intersection between the provided values and the + original index values. + This requires index values to be a precise match. Index values in Rerun are represented as i64 sequence counts or nanoseconds. This API does not expose an interface in floating point seconds, as the numerical conversion would risk false mismatches. """ ... + def filter_is_not_null(self, column: AnyColumn) -> RecordingView: + """ + Filter the view to only include rows where the given column is not null. + + This corresponds to rows for index values where this component was provided to Rerun explicitly + via `.log()` or `.send_columns()`. + """ + ... + + def using_index_values(self, values: IndexValuesLike) -> RecordingView: + """ + Replace the index in the view with the provided values. + + The output view will always have the same number of rows as the provided values, even if + those rows are empty. Use with `.fill_latest_at()` to populate these rows with the most + recent data. + + This requires index values to be a precise match. Index values in Rerun are + represented as i64 sequence counts or nanoseconds. This API does not expose an interface + in floating point seconds, as the numerical conversion would risk false mismatches. + """ + ... + + def fill_latest_at(self) -> RecordingView: + """Populate any null values in a row with the latest valid data on the timeline.""" + ... + def select(self, *args: AnyColumn, columns: Optional[Sequence[AnyColumn]] = None) -> pa.RecordBatchReader: ... class Recording: diff --git a/rerun_py/src/dataframe.rs b/rerun_py/src/dataframe.rs index 6651fd2020b6..00c573c9d964 100644 --- a/rerun_py/src/dataframe.rs +++ b/rerun_py/src/dataframe.rs @@ -553,6 +553,40 @@ impl PyRecordingView { query_expression, }) } + + fn filter_is_not_null(&self, column: AnyComponentColumn) -> Self { + let column = column.into_selector(); + + let mut query_expression = self.query_expression.clone(); + query_expression.filtered_point_of_view = Some(column); + + Self { + recording: self.recording.clone(), + query_expression, + } + } + + fn using_index_values(&self, values: IndexValuesLike<'_>) -> PyResult { + let values = values.to_index_values()?; + + let mut query_expression = self.query_expression.clone(); + query_expression.using_index_values = Some(values); + + Ok(Self { + recording: self.recording.clone(), + query_expression, + }) + } + + fn fill_latest_at(&self) -> Self { + let mut query_expression = self.query_expression.clone(); + query_expression.sparse_fill_strategy = SparseFillStrategy::LatestAtGlobal; + + Self { + recording: self.recording.clone(), + query_expression, + } + } } impl PyRecording { diff --git a/rerun_py/tests/unit/test_dataframe.py b/rerun_py/tests/unit/test_dataframe.py index 06b967bdb937..5532ca283fbc 100644 --- a/rerun_py/tests/unit/test_dataframe.py +++ b/rerun_py/tests/unit/test_dataframe.py @@ -86,6 +86,11 @@ def setup_method(self) -> None: type=rr.components.Position3D.arrow_type(), ) + self.empty_pos = pa.array( + [], + type=rr.components.Position3D.arrow_type(), + ) + def test_recording_info(self) -> None: assert self.recording.application_id() == APP_ID assert self.recording.recording_id() == str(RECORDING_ID) @@ -188,6 +193,55 @@ def test_index_values(self) -> None: with pytest.raises(TypeError): view.filter_index_values(pa.array([1.0, 2.0], type=pa.float64())) + def test_using_index_values(self) -> None: + view = self.recording.view(index="my_index", contents="points") + view = view.using_index_values([0, 5, 9]) + + table = view.select().read_all().combine_chunks() + + # my_index, log_time, log_tick, points, colors + assert table.num_columns == 5 + assert table.num_rows == 3 + + expected_index = pa.chunked_array([ + pa.array( + [0, 5, 9], + type=pa.int64(), + ) + ]) + + assert table.column("my_index").equals(expected_index) + assert not table.column("/points:Position3D")[0].is_valid + assert not table.column("/points:Position3D")[1].is_valid + assert not table.column("/points:Position3D")[2].is_valid + + table = view.fill_latest_at().select().read_all().combine_chunks() + + assert table.num_columns == 5 + assert table.num_rows == 3 + + assert table.column("my_index").equals(expected_index) + assert not table.column("/points:Position3D")[0].is_valid + assert table.column("/points:Position3D")[1].values.equals(self.expected_pos0) + assert table.column("/points:Position3D")[2].values.equals(self.expected_pos1) + + def test_filter_is_not_null(self) -> None: + view = self.recording.view(index="my_index", contents="points") + + color = rr.dataframe.ComponentColumnSelector("points", rr.components.Color) + + view = view.filter_is_not_null(color) + + table = view.select().read_all() + + # my_index, log_time, log_tick, points, colors + assert table.num_columns == 5 + assert table.num_rows == 1 + + assert table.column("my_index")[0].equals(self.expected_index1[0]) + + assert table.column("/points:Position3D")[0].values.equals(self.expected_pos1) + def test_view_syntax(self) -> None: good_content_expressions = [ {"points": rr.components.Position3D}, From ad631cd76e90099205ccf7ac021a2a41aaef3096 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 11 Oct 2024 16:30:39 +0200 Subject: [PATCH 11/33] Enable (n)asm rav1d on Mac & Windows via `nasm` feature (#7694) ### What Related to * #7671 * #7605 * #7588 Biting the bullet and split the feature on our rav1d fork: https://github.com/rerun-io/rav1d/compare/emilk/dav1d-interface...rerun-io:rav1d:andreas/disable-asm-linux Testing done: * wsl linux release build works now (didn't before) * windows build still works * shows no-asm warning if compiled with out nasm * works otherwise * added a `panic` under `cfg(asm)` in one of the interface functions (now removed again) .. then: * linux still worked * windows hit that panic when compiled with nasm feature ### Checklist * [x] main ci passes * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7694?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7694?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7694) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Emil Ernerfeldt --- Cargo.lock | 3 ++- crates/store/re_video/Cargo.toml | 10 ++++++---- crates/store/re_video/src/decode/av1.rs | 4 ++-- crates/top/rerun-cli/Cargo.toml | 2 +- crates/top/rerun/Cargo.toml | 2 +- rerun_py/Cargo.toml | 2 +- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab71bbc4dffc..390eb91b4723 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4758,7 +4758,7 @@ dependencies = [ [[package]] name = "rav1d" version = "1.0.0" -source = "git+https://github.com/rerun-io/rav1d?branch=emilk/dav1d-interface#d3acfb077eac7759f94279ec9a81edd7d0c409ed" +source = "git+https://github.com/rerun-io/rav1d?rev=a9059f6a02e68cf2aba3795cc370c72f695c4730#a9059f6a02e68cf2aba3795cc370c72f695c4730" dependencies = [ "assert_matches", "atomig", @@ -4766,6 +4766,7 @@ dependencies = [ "bitflags 2.6.0", "cc", "cfg-if", + "cfg_aliases 0.2.1", "libc", "nasm-rs", "parking_lot", diff --git a/crates/store/re_video/Cargo.toml b/crates/store/re_video/Cargo.toml index afc07c39dcd3..ab63551b1016 100644 --- a/crates/store/re_video/Cargo.toml +++ b/crates/store/re_video/Cargo.toml @@ -31,9 +31,11 @@ av1 = ["dep:dav1d"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. -# TODO(#7671): this feature flag currently does nothing -# nasm = ["dav1d?/default"] # The default feature set of dav1d has asm enabled -nasm = [] ## TODO(#7671): fix Linux build +# TODO(#7671): this feature flag currently does nothing on Linux. +nasm = [ + # The default feature set of our dav1d fork has asm enabled (except on Linux, see above) + "dav1d?/default", +] [dependencies] re_log.workspace = true @@ -52,7 +54,7 @@ thiserror.workspace = true # If this package fails to build, install `nasm` locally, or build through `pixi`. # See https://github.com/rerun-io/rav1d/pull/1 # TODO(#7588): publish this fork of rav1d -dav1d = { git = "https://github.com/rerun-io/rav1d", branch = "emilk/dav1d-interface", package = "rav1d", optional = true, default-features = false, features = [ +dav1d = { git = "https://github.com/rerun-io/rav1d", rev = "a9059f6a02e68cf2aba3795cc370c72f695c4730", package = "rav1d", optional = true, default-features = false, features = [ # We opt-out of wasm features so we don't need `nasm` installed. It's still pretty fast. "bitdepth_8", ] } diff --git a/crates/store/re_video/src/decode/av1.rs b/crates/store/re_video/src/decode/av1.rs index dea52895e2e7..983b918a7fb6 100644 --- a/crates/store/re_video/src/decode/av1.rs +++ b/crates/store/re_video/src/decode/av1.rs @@ -16,9 +16,9 @@ impl SyncDav1dDecoder { pub fn new() -> Result { re_tracing::profile_function!(); - // TODO(#7671): enable this warning again when the `nasm` feature actually does something + // TODO(#7671): enable this warning again on Linux when the `nasm` feature actually does something #[allow(clippy::overly_complex_bool_expr)] - if false && !cfg!(feature = "nasm") { + if !cfg!(target_os = "linux") && !cfg!(feature = "nasm") { re_log::warn_once!( "NOTE: native AV1 video decoder is running extra slowly. \ Speed it up by compiling Rerun with the `nasm` feature enabled. \ diff --git a/crates/top/rerun-cli/Cargo.toml b/crates/top/rerun-cli/Cargo.toml index 1f0f0ef3c5b0..2cf4ac433a67 100644 --- a/crates/top/rerun-cli/Cargo.toml +++ b/crates/top/rerun-cli/Cargo.toml @@ -43,7 +43,7 @@ default = ["native_viewer", "web_viewer"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. -# TODO(#7671): this feature flag currently does nothing +# TODO(#7671): this feature flag currently does nothing on linux. nasm = ["rerun/nasm"] ## Support spawning a native viewer. diff --git a/crates/top/rerun/Cargo.toml b/crates/top/rerun/Cargo.toml index dfc1e8bccdde..a6fe1b87e346 100644 --- a/crates/top/rerun/Cargo.toml +++ b/crates/top/rerun/Cargo.toml @@ -73,7 +73,7 @@ log = ["dep:env_logger", "dep:log"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. -# TODO(#7671): this feature flag currently does nothing +# TODO(#7671): this feature flag currently does nothing on linux. nasm = ["re_video/nasm"] ## Support spawning a native viewer. diff --git a/rerun_py/Cargo.toml b/rerun_py/Cargo.toml index 9c19c36591ba..992d5b5f5977 100644 --- a/rerun_py/Cargo.toml +++ b/rerun_py/Cargo.toml @@ -30,7 +30,7 @@ extension-module = ["pyo3/extension-module"] ## Enable faster native video decoding with assembly. ## You need to install [nasm](https://nasm.us/) to compile with this feature. -# TODO(#7671): this feature flag currently does nothing +# TODO(#7671): this feature flag currently does nothing on linux. nasm = ["re_video/nasm"] ## Support serving a web viewer over HTTP with `serve()`. From 9f34cb72ad88a9289f913c10c0b4c1d6f748a061 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 11 Oct 2024 16:56:18 +0200 Subject: [PATCH 12/33] Improve docs about video support (#7687) We do support AV1 on native, and now the docs say so too. * Closes https://github.com/rerun-io/rerun/issues/7662 ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7687?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7687?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide * [x] I've read the docs preview at https://landing-e6yens1hp-rerun.vercel.app/docs/reference/video - [PR Build Summary](https://build.rerun.io/pr/7687) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Andreas Reich --- .../rerun/archetypes/asset_video.fbs | 6 ++-- .../archetypes/video_frame_reference.fbs | 2 +- .../re_types/src/archetypes/asset_video.rs | 6 ++-- .../src/archetypes/video_frame_reference.rs | 2 +- .../reference/types/archetypes/asset_video.md | 6 ++-- .../types/archetypes/video_frame_reference.md | 2 +- docs/content/reference/video.md | 33 +++++++++++-------- .../src/rerun/archetypes/asset_video.hpp | 6 ++-- .../archetypes/video_frame_reference.hpp | 2 +- .../rerun_sdk/rerun/archetypes/asset_video.py | 6 ++-- .../rerun/archetypes/video_frame_reference.py | 2 +- 11 files changed, 39 insertions(+), 34 deletions(-) diff --git a/crates/store/re_types/definitions/rerun/archetypes/asset_video.fbs b/crates/store/re_types/definitions/rerun/archetypes/asset_video.fbs index 0190d6f0eb33..2a4c27ac48a3 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/asset_video.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/asset_video.fbs @@ -2,10 +2,10 @@ namespace rerun.archetypes; /// A video binary. /// -/// NOTE: Videos can only be viewed in the Rerun web viewer. -/// Only MP4 containers with a limited number of codecs are currently supported, and not in all browsers. +/// Only MP4 containers with AV1 are generally supported, +/// though the web viewer supports more video codecs, depending on browser. /// -/// See for details of what is and isn't supported. +/// See for details of what is and isn't supported. /// /// In order to display a video, you also need to log a [archetypes.VideoFrameReference] for each frame. /// diff --git a/crates/store/re_types/definitions/rerun/archetypes/video_frame_reference.fbs b/crates/store/re_types/definitions/rerun/archetypes/video_frame_reference.fbs index 481d31c92a0f..b0f749184cc5 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/video_frame_reference.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/video_frame_reference.fbs @@ -5,7 +5,7 @@ namespace rerun.archetypes; /// Used to display individual video frames from a [archetypes.AssetVideo]. /// To show an entire video, a video frame reference for each frame of the video should be logged. /// -/// See for details of what is and isn't supported. +/// See for details of what is and isn't supported. /// /// \example archetypes/video_auto_frames title="Video with automatically determined frames" image="https://static.rerun.io/video_manual_frames/320a44e1e06b8b3a3161ecbbeae3e04d1ccb9589/1200w.png" /// \example archetypes/video_manual_frames title="Demonstrates manual use of video frame references" image="https://static.rerun.io/video_manual_frames/9f41c00f84a98cc3f26875fba7c1d2fa2bad7151/1200w.png" diff --git a/crates/store/re_types/src/archetypes/asset_video.rs b/crates/store/re_types/src/archetypes/asset_video.rs index d0c64526b632..ea790784319c 100644 --- a/crates/store/re_types/src/archetypes/asset_video.rs +++ b/crates/store/re_types/src/archetypes/asset_video.rs @@ -20,10 +20,10 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: A video binary. /// -/// NOTE: Videos can only be viewed in the Rerun web viewer. -/// Only MP4 containers with a limited number of codecs are currently supported, and not in all browsers. +/// Only MP4 containers with AV1 are generally supported, +/// though the web viewer supports more video codecs, depending on browser. /// -/// See for details of what is and isn't supported. +/// See for details of what is and isn't supported. /// /// In order to display a video, you also need to log a [`archetypes::VideoFrameReference`][crate::archetypes::VideoFrameReference] for each frame. /// diff --git a/crates/store/re_types/src/archetypes/video_frame_reference.rs b/crates/store/re_types/src/archetypes/video_frame_reference.rs index 42143f2935f6..08380d586d21 100644 --- a/crates/store/re_types/src/archetypes/video_frame_reference.rs +++ b/crates/store/re_types/src/archetypes/video_frame_reference.rs @@ -23,7 +23,7 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// Used to display individual video frames from a [`archetypes::AssetVideo`][crate::archetypes::AssetVideo]. /// To show an entire video, a video frame reference for each frame of the video should be logged. /// -/// See for details of what is and isn't supported. +/// See for details of what is and isn't supported. /// /// ## Examples /// diff --git a/docs/content/reference/types/archetypes/asset_video.md b/docs/content/reference/types/archetypes/asset_video.md index 34ffa59c7bf3..4e9f2c488d27 100644 --- a/docs/content/reference/types/archetypes/asset_video.md +++ b/docs/content/reference/types/archetypes/asset_video.md @@ -5,10 +5,10 @@ title: "AssetVideo" A video binary. -NOTE: Videos can only be viewed in the Rerun web viewer. -Only MP4 containers with a limited number of codecs are currently supported, and not in all browsers. +Only MP4 containers with AV1 are generally supported, +though the web viewer supports more video codecs, depending on browser. -See for details of what is and isn't supported. +See for details of what is and isn't supported. In order to display a video, you also need to log a [`archetypes.VideoFrameReference`](https://rerun.io/docs/reference/types/archetypes/video_frame_reference?speculative-link) for each frame. diff --git a/docs/content/reference/types/archetypes/video_frame_reference.md b/docs/content/reference/types/archetypes/video_frame_reference.md index 311d6e6f7f2d..5f33f501aa74 100644 --- a/docs/content/reference/types/archetypes/video_frame_reference.md +++ b/docs/content/reference/types/archetypes/video_frame_reference.md @@ -8,7 +8,7 @@ References a single video frame. Used to display individual video frames from a [`archetypes.AssetVideo`](https://rerun.io/docs/reference/types/archetypes/asset_video?speculative-link). To show an entire video, a video frame reference for each frame of the video should be logged. -See for details of what is and isn't supported. +See for details of what is and isn't supported. ## Components diff --git a/docs/content/reference/video.md b/docs/content/reference/video.md index f40693e42cb8..e7948d51a202 100644 --- a/docs/content/reference/video.md +++ b/docs/content/reference/video.md @@ -23,26 +23,32 @@ This gives the best compression ratio, reducing file sizes and bandwidth require snippet: archetypes/video_auto_frames -## `AssetVideo` limitations -Video support is new in Rerun, and has several limitations: +## Video playback limitations +Video support is new in Rerun, and has a few limitations: -* [#7298](https://github.com/rerun-io/rerun/issues/7298): Video playback only works in the web viewer * [#7354](https://github.com/rerun-io/rerun/issues/7354): Only the MP4 container format is supported +* [#7298](https://github.com/rerun-io/rerun/issues/7298): Only the AV1 codec is supported in the native viewer * [#5181](https://github.com/rerun-io/rerun/issues/5181): There is no audio support +* [#7594](https://github.com/rerun-io/rerun/issues/7594): HDR video is not supported * There is no video encoder in the Rerun SDK, so you need to create the video file yourself -* Only a limited sets of codecs are supported (see below) +* A limited sets of codecs are supported on web (see below) -## Web viewer support -As of writing, playback of `AssetVideo` is only supported on the web viewer. -Native video playback is coming, and can be tracked [in this GitHub issue](https://github.com/rerun-io/rerun/issues/7298). - -Video playback is done using the browser's own video decoder, so the supported codecs depend on your browser. - -Overall, we recommend using Chrome or another Chromium-based browser, as it seems to have the best video support as of writing. +## Streaming video +Rerun does not yet support streaming video support. For scenarios where you don't need live video, you can work around this limitation by logging many small `AssetVideo`s to the same Entity Path. See [#7484](https://github.com/rerun-io/rerun/issues/7484) for more. +## Codec support When choosing a codec, we recommend [AV1](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs#av1), as it seems to have the best overall playback support while also having very high compression quality. -Since AV1 is patent-free, it is also likely the first codec we will support in the native viewer. +AV1 is also patent-free, and is the only codec we currently support in the native viewer (see [#7298](https://github.com/rerun-io/rerun/issues/7298)). H.264/avc is another popular choice, and native support for that is coming soon. + +### Native viewer +In the native viewer, AV1 is the only supported codec. H.264 is coming soon ([#7298](https://github.com/rerun-io/rerun/issues/7298)). + + +### Web viewer +Video playback in the Rerun Web Viewer is done using the browser's own video decoder, so the supported codecs depend on your browser. + +Overall, we recommend using Chrome or another Chromium-based browser, as it seems to have the best video support as of writing. For decoding video in the Web Viewer, we use the [WebCodecs API](https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API). This API enables us to take advantage of the browser's hardware accelerated video decoding capabilities. @@ -58,7 +64,7 @@ With that in mind, here are the browsers which we have tested and verified to ge [^1]: Firefox on Linux has been observed to [stutter when playing back H.264 video](https://github.com/rerun-io/rerun/issues/7532). [^2]: Any Chromium-based browser should work, but we don't test all of them. -[^3]: Chrome on Windows has been observed to stutter on playback. It can be mitigated by [using software decoding](https://rerun.io/docs/getting-started/troubleshooting#video-stuttering), but this may lead to high memory usage. See also https://github.com/rerun-io/rerun/issues/7595. +[^3]: Chrome on Windows has been observed to stutter on playback. It can be mitigated by [using software decoding](https://rerun.io/docs/getting-started/troubleshooting#video-stuttering), but this may lead to high memory usage. See [#7595](https://github.com/rerun-io/rerun/issues/7595). When it comes to codecs, we aim to support any codec which the browser supports, but we currently cannot guarantee that all of them will work. For more information about @@ -77,7 +83,6 @@ At the moment, we test the following codecs: [^6]: Safari/WebKit has been observed suttering when playing `hvc1` but working fine with `hevc1`. Despite support being advertised Safari 16.5 has been observed not support H.265 decoding. [^7]: Only supported if hardware encoding is available. Therefore always affected by Windows stuttering issues, see [^3]. -(TODO(#7594))[https://github.com/rerun-io/rerun/issues/7594]: HDR video is generally not supported at this point. ## Links * [Web video codec guide, by Mozilla](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs) diff --git a/rerun_cpp/src/rerun/archetypes/asset_video.hpp b/rerun_cpp/src/rerun/archetypes/asset_video.hpp index 3d9dd80f1054..6748876bccbf 100644 --- a/rerun_cpp/src/rerun/archetypes/asset_video.hpp +++ b/rerun_cpp/src/rerun/archetypes/asset_video.hpp @@ -21,10 +21,10 @@ namespace rerun::archetypes { /// **Archetype**: A video binary. /// - /// NOTE: Videos can only be viewed in the Rerun web viewer. - /// Only MP4 containers with a limited number of codecs are currently supported, and not in all browsers. + /// Only MP4 containers with AV1 are generally supported, + /// though the web viewer supports more video codecs, depending on browser. /// - /// See for details of what is and isn't supported. + /// See for details of what is and isn't supported. /// /// In order to display a video, you also need to log a `archetypes::VideoFrameReference` for each frame. /// diff --git a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp index 254279dde5ce..421841e33496 100644 --- a/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp +++ b/rerun_cpp/src/rerun/archetypes/video_frame_reference.hpp @@ -22,7 +22,7 @@ namespace rerun::archetypes { /// Used to display individual video frames from a `archetypes::AssetVideo`. /// To show an entire video, a video frame reference for each frame of the video should be logged. /// - /// See for details of what is and isn't supported. + /// See for details of what is and isn't supported. /// /// ## Examples /// diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py index 4709296b2a58..65c41a918d95 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py @@ -21,10 +21,10 @@ class AssetVideo(AssetVideoExt, Archetype): """ **Archetype**: A video binary. - NOTE: Videos can only be viewed in the Rerun web viewer. - Only MP4 containers with a limited number of codecs are currently supported, and not in all browsers. + Only MP4 containers with AV1 are generally supported, + though the web viewer supports more video codecs, depending on browser. - See for details of what is and isn't supported. + See for details of what is and isn't supported. In order to display a video, you also need to log a [`archetypes.VideoFrameReference`][rerun.archetypes.VideoFrameReference] for each frame. diff --git a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py index 5ae51042c52e..71ffdaaae9f1 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py @@ -26,7 +26,7 @@ class VideoFrameReference(Archetype): Used to display individual video frames from a [`archetypes.AssetVideo`][rerun.archetypes.AssetVideo]. To show an entire video, a video frame reference for each frame of the video should be logged. - See for details of what is and isn't supported. + See for details of what is and isn't supported. Examples -------- From fd46ce3142bbe823de0417b105bef0c794d0be3f Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 11 Oct 2024 17:04:03 +0200 Subject: [PATCH 13/33] Fix main (unordered map that shouldnt be here) (#7697) --- crates/store/re_chunk_store/src/store.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/store/re_chunk_store/src/store.rs b/crates/store/re_chunk_store/src/store.rs index 28d825aa9af3..4456a2a0e231 100644 --- a/crates/store/re_chunk_store/src/store.rs +++ b/crates/store/re_chunk_store/src/store.rs @@ -333,7 +333,8 @@ pub struct ChunkStore { // different datatype for a given component. pub(crate) type_registry: IntMap, - pub(crate) per_column_metadata: IntMap>, + pub(crate) per_column_metadata: + BTreeMap>, pub(crate) chunks_per_chunk_id: BTreeMap>, From bf26fb623eced0a79cd19242ea18c60f2ff0695d Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Fri, 11 Oct 2024 17:58:35 +0200 Subject: [PATCH 14/33] Use GPU based transfer to do chroma conversions of native decoder output (#7682) ### What * Important chunk of https://github.com/rerun-io/rerun/issues/7605 * Related to https://github.com/rerun-io/rerun/issues/7608 * todo: create a new ticket for bgr shenanigans and close this one --- Fixes performance issues with our previous inefficient cpu based chroma conversion: ![image](https://github.com/user-attachments/assets/fed67eb9-902b-43d8-bbd6-8574a5f3b18d) ... and fixes color space issues: Top left: now Top right: before Bottom: VLC ![image](https://github.com/user-attachments/assets/f5b797bd-e12d-46b0-96dd-32176d43e78c) --- There was an oversight in the conversion pipeline that if fixed now: It only allowed for creating new textures. Now it can also update existing textures! This means that it takes a target texture from the outside. Naturally, there's some constraints on what the target texture looks like and as a consequence I added some validation for that. Could be more, but I think this is solid enough for our purposes :) ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7682?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7682?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7682) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --- crates/store/re_video/examples/frames.rs | 7 +- crates/store/re_video/src/decode/av1.rs | 431 +++++++++--------- crates/store/re_video/src/decode/mod.rs | 40 ++ .../src/allocator/cpu_write_gpu_read_belt.rs | 2 +- crates/viewer/re_renderer/src/renderer/mod.rs | 2 +- .../image_data_to_texture.rs | 152 ++++-- .../re_renderer/src/resource_managers/mod.rs | 3 +- .../src/resource_managers/texture_manager.rs | 18 +- .../src/resource_managers/yuv_converter.rs | 51 +-- .../re_renderer/src/video/decoder/mod.rs | 2 +- .../src/video/decoder/native_decoder.rs | 89 ++-- crates/viewer/re_renderer/src/video/mod.rs | 3 + .../src/wgpu_resources/resource.rs | 2 +- .../src/gpu_bridge/image_to_gpu.rs | 12 +- 14 files changed, 488 insertions(+), 326 deletions(-) diff --git a/crates/store/re_video/examples/frames.rs b/crates/store/re_video/examples/frames.rs index 877c20bdff1d..0ad5684d7ea1 100644 --- a/crates/store/re_video/examples/frames.rs +++ b/crates/store/re_video/examples/frames.rs @@ -36,15 +36,16 @@ fn main() { video.config.coded_height ); - let mut decoder = create_decoder(&video); + let mut decoder = create_decoder(video_path, &video); write_video_frames(&video, decoder.as_mut(), &output_dir); } -fn create_decoder(video: &VideoData) -> Box { +fn create_decoder(debug_name: &str, video: &VideoData) -> Box { if video.config.is_av1() { Box::new( - re_video::decode::av1::SyncDav1dDecoder::new().expect("Failed to start AV1 decoder"), + re_video::decode::av1::SyncDav1dDecoder::new(debug_name.to_owned()) + .expect("Failed to start AV1 decoder"), ) } else { panic!("Unsupported codec: {}", video.human_readable_codec_string()); diff --git a/crates/store/re_video/src/decode/av1.rs b/crates/store/re_video/src/decode/av1.rs index 983b918a7fb6..61c29e2a0f4f 100644 --- a/crates/store/re_video/src/decode/av1.rs +++ b/crates/store/re_video/src/decode/av1.rs @@ -2,18 +2,39 @@ use std::sync::atomic::{AtomicBool, Ordering}; -use dav1d::{PixelLayout, PlanarImageComponent}; - use crate::Time; +use dav1d::{PixelLayout, PlanarImageComponent}; -use super::{Chunk, Error, Frame, OutputCallback, PixelFormat, Result, SyncDecoder}; +use super::{ + Chunk, ColorPrimaries, Error, Frame, OutputCallback, PixelFormat, Result, SyncDecoder, + YuvPixelLayout, YuvRange, +}; pub struct SyncDav1dDecoder { decoder: dav1d::Decoder, + debug_name: String, +} + +impl SyncDecoder for SyncDav1dDecoder { + fn submit_chunk(&mut self, should_stop: &AtomicBool, chunk: Chunk, on_output: &OutputCallback) { + re_tracing::profile_function!(); + self.submit_chunk(chunk, on_output); + self.output_frames(should_stop, on_output); + } + + /// Clear and reset everything + fn reset(&mut self) { + re_tracing::profile_function!(); + + self.decoder.flush(); + + debug_assert!(matches!(self.decoder.get_picture(), Err(dav1d::Error::Again)), + "There should be no pending pictures, since we output them directly after submitting a chunk."); + } } impl SyncDav1dDecoder { - pub fn new() -> Result { + pub fn new(debug_name: String) -> Result { re_tracing::profile_function!(); // TODO(#7671): enable this warning again on Linux when the `nasm` feature actually does something @@ -37,238 +58,242 @@ impl SyncDav1dDecoder { let decoder = dav1d::Decoder::with_settings(&settings)?; - Ok(Self { decoder }) + Ok(Self { + decoder, + debug_name, + }) } -} -impl SyncDecoder for SyncDav1dDecoder { - fn submit_chunk(&mut self, should_stop: &AtomicBool, chunk: Chunk, on_output: &OutputCallback) { + fn submit_chunk(&mut self, chunk: Chunk, on_output: &OutputCallback) { re_tracing::profile_function!(); - submit_chunk(&mut self.decoder, chunk, on_output); - output_frames(should_stop, &mut self.decoder, on_output); + econtext::econtext_function_data!(format!("chunk timestamp: {:?}", chunk.timestamp)); + + re_tracing::profile_scope!("send_data"); + match self.decoder.send_data( + chunk.data, + None, + Some(chunk.timestamp.0), + Some(chunk.duration.0), + ) { + Ok(()) => {} + Err(err) => { + debug_assert!(err != dav1d::Error::Again, "Bug in AV1 decoder: send_data returned `Error::Again`. This shouldn't happen, since we process all images in a chunk right away"); + on_output(Err(Error::Dav1d(err))); + } + }; } - /// Clear and reset everything - fn reset(&mut self) { + /// Returns the number of new frames. + fn output_frames(&mut self, should_stop: &AtomicBool, on_output: &OutputCallback) -> usize { re_tracing::profile_function!(); - - self.decoder.flush(); - - debug_assert!(matches!(self.decoder.get_picture(), Err(dav1d::Error::Again)), - "There should be no pending pictures, since we output them directly after submitting a chunk."); - } -} - -fn submit_chunk(decoder: &mut dav1d::Decoder, chunk: Chunk, on_output: &OutputCallback) { - re_tracing::profile_function!(); - econtext::econtext_function_data!(format!("chunk timestamp: {:?}", chunk.timestamp)); - - re_tracing::profile_scope!("send_data"); - match decoder.send_data( - chunk.data, - None, - Some(chunk.timestamp.0), - Some(chunk.duration.0), - ) { - Ok(()) => {} - Err(err) => { - debug_assert!(err != dav1d::Error::Again, "Bug in AV1 decoder: send_data returned `Error::Again`. This shouldn't happen, since we process all images in a chunk right away"); - on_output(Err(Error::Dav1d(err))); - } - }; -} - -/// Returns the number of new frames. -fn output_frames( - should_stop: &AtomicBool, - decoder: &mut dav1d::Decoder, - on_output: &OutputCallback, -) -> usize { - re_tracing::profile_function!(); - let mut count = 0; - while !should_stop.load(Ordering::SeqCst) { - let picture = { - econtext::econtext!("get_picture"); - decoder.get_picture() - }; - match picture { - Ok(picture) => { - output_picture(&picture, on_output); - count += 1; - } - Err(dav1d::Error::Again) => { - // We need to submit more chunks to get more pictures - break; - } - Err(err) => { - on_output(Err(Error::Dav1d(err))); + let mut count = 0; + while !should_stop.load(Ordering::SeqCst) { + let picture = { + econtext::econtext!("get_picture"); + self.decoder.get_picture() + }; + match picture { + Ok(picture) => { + output_picture(&self.debug_name, &picture, on_output); + count += 1; + } + Err(dav1d::Error::Again) => { + // We need to submit more chunks to get more pictures + break; + } + Err(err) => { + on_output(Err(Error::Dav1d(err))); + } } } + count } - count } -fn output_picture(picture: &dav1d::Picture, on_output: &(dyn Fn(Result) + Send + Sync)) { +fn output_picture( + debug_name: &str, + picture: &dav1d::Picture, + on_output: &(dyn Fn(Result) + Send + Sync), +) { // TODO(jan): support other parameters? // What do these even do: // - matrix_coefficients - // - color_range - // - color_primaries // - transfer_characteristics - let frame = Frame { - data: match picture.pixel_layout() { - PixelLayout::I400 => i400_to_rgba(picture), - PixelLayout::I420 => i420_to_rgba(picture), - PixelLayout::I422 => i422_to_rgba(picture), - PixelLayout::I444 => i444_to_rgba(picture), + let data = { + re_tracing::profile_scope!("copy_picture_data"); + + match picture.pixel_layout() { + PixelLayout::I400 => picture.plane(PlanarImageComponent::Y).to_vec(), + PixelLayout::I420 | PixelLayout::I422 | PixelLayout::I444 => { + // TODO(#7594): If `picture.bit_depth()` isn't 8 we have a problem: + // We can't handle high bit depths yet and the YUV converter at the other side + // bases its opinion on what an acceptable number of incoming bytes is on this. + // So we just clamp to that expectation, ignoring `picture.stride(PlanarImageComponent::Y)` & friends. + // Note that `bit_depth` is either 8 or 16, which is semi-independent `bits_per_component` (which is None/8/10/12). + if picture.bit_depth() != 8 { + re_log::warn_once!( + "Video {debug_name:?} uses {} bis per component. Only a bit depth of 8 bit is currently unsupported.", + picture.bits_per_component().map_or(picture.bit_depth(), |bpc| bpc.0) + ); + } + + let height_y = picture.height() as usize; + let height_uv = match picture.pixel_layout() { + PixelLayout::I400 => 0, + PixelLayout::I420 => height_y / 2, + PixelLayout::I422 | PixelLayout::I444 => height_y, + }; + + let packed_stride_y = picture.width() as usize; + let actual_stride_y = picture.stride(PlanarImageComponent::Y) as usize; + + let packed_stride_uv = match picture.pixel_layout() { + PixelLayout::I400 => 0, + PixelLayout::I420 | PixelLayout::I422 => packed_stride_y / 2, + PixelLayout::I444 => packed_stride_y, + }; + let actual_stride_uv = picture.stride(PlanarImageComponent::U) as usize; // U / V stride is always the same. + + let num_packed_bytes_y = packed_stride_y * height_y; + let num_packed_bytes_uv = packed_stride_uv * height_uv; + + if actual_stride_y == packed_stride_y && actual_stride_uv == packed_stride_uv { + // Best case scenario: There's no additional strides at all, so we can just copy the data directly. + // TODO(andreas): This still has *significant* overhead for 8k video. Can we take ownership of the data instead without a copy? + re_tracing::profile_scope!("fast path"); + let plane_y = &picture.plane(PlanarImageComponent::Y)[0..num_packed_bytes_y]; + let plane_u = &picture.plane(PlanarImageComponent::U)[0..num_packed_bytes_uv]; + let plane_v = &picture.plane(PlanarImageComponent::V)[0..num_packed_bytes_uv]; + [plane_y, plane_u, plane_v].concat() + } else { + // At least either y or u/v have strides. + // + // We could make our image ingestion pipeline even more sophisticated and pass that stride information through. + // But given that this is a matter of replacing a single large memcpy with a few hundred _still_ quite large ones, + // this should not make a lot of difference (citation needed!). + + let mut data = Vec::with_capacity(num_packed_bytes_y + num_packed_bytes_uv * 2); + { + let plane = picture.plane(PlanarImageComponent::Y); + if packed_stride_y == actual_stride_y { + data.extend_from_slice(&plane[0..num_packed_bytes_y]); + } else { + re_tracing::profile_scope!("slow path, y-plane"); + + for y in 0..height_y { + let offset = y * actual_stride_y; + data.extend_from_slice(&plane[offset..(offset + packed_stride_y)]); + } + } + } + for comp in [PlanarImageComponent::U, PlanarImageComponent::V] { + let plane = picture.plane(comp); + if actual_stride_uv == packed_stride_uv { + data.extend_from_slice(&plane[0..num_packed_bytes_uv]); + } else { + re_tracing::profile_scope!("slow path, u/v-plane"); + + for y in 0..height_uv { + let offset = y * actual_stride_uv; + data.extend_from_slice(&plane[offset..(offset + packed_stride_uv)]); + } + } + } + + data + } + } + } + }; + + let format = PixelFormat::Yuv { + layout: match picture.pixel_layout() { + PixelLayout::I400 => YuvPixelLayout::Y400, + PixelLayout::I420 => YuvPixelLayout::Y_U_V420, + PixelLayout::I422 => YuvPixelLayout::Y_U_V422, + PixelLayout::I444 => YuvPixelLayout::Y_U_V444, }, + range: match picture.color_range() { + dav1d::pixel::YUVRange::Limited => YuvRange::Limited, + dav1d::pixel::YUVRange::Full => YuvRange::Full, + }, + primaries: color_primaries(debug_name, picture), + }; + + let frame = Frame { + data, width: picture.width(), height: picture.height(), - format: PixelFormat::Rgba8Unorm, + format, timestamp: Time(picture.timestamp().unwrap_or(0)), duration: Time(picture.duration()), }; on_output(Ok(frame)); } -fn rgba_from_yuv(y: u8, u: u8, v: u8) -> [u8; 4] { - let (y, u, v) = (f32::from(y), f32::from(u), f32::from(v)); - - // Adjust for color range - let y = (y - 16.0) / 219.0; - let u = (u - 128.0) / 224.0; - let v = (v - 128.0) / 224.0; - - // BT.601 coefficients - let r = y + 1.402 * v; - let g = y - 0.344136 * u - 0.714136 * v; - let b = y + 1.772 * u; - - [ - (r.clamp(0.0, 1.0) * 255.0) as u8, - (g.clamp(0.0, 1.0) * 255.0) as u8, - (b.clamp(0.0, 1.0) * 255.0) as u8, - 255, // Alpha channel, fully opaque - ] -} - -fn i400_to_rgba(picture: &dav1d::Picture) -> Vec { - re_tracing::profile_function!(); - - let width = picture.width() as usize; - let height = picture.height() as usize; - let y_plane = picture.plane(PlanarImageComponent::Y); - let y_stride = picture.stride(PlanarImageComponent::Y) as usize; - - let mut rgba = Vec::with_capacity(width * height * 4); - - for y in 0..height { - for x in 0..width { - let y_value = y_plane[y * y_stride + x]; - let rgba_pixel = rgba_from_yuv(y_value, 128, 128); - - let offset = y * width * 4 + x * 4; - rgba[offset] = rgba_pixel[0]; - rgba[offset + 1] = rgba_pixel[1]; - rgba[offset + 2] = rgba_pixel[2]; - rgba[offset + 3] = rgba_pixel[3]; +fn color_primaries(debug_name: &str, picture: &dav1d::Picture) -> ColorPrimaries { + #[allow(clippy::match_same_arms)] + match picture.color_primaries() { + dav1d::pixel::ColorPrimaries::Reserved + | dav1d::pixel::ColorPrimaries::Reserved0 + | dav1d::pixel::ColorPrimaries::Unspecified => { + // This happens quite often. Don't issue a warning, that would be noise! + + if picture.transfer_characteristic() == dav1d::pixel::TransferCharacteristic::SRGB { + // If the transfer characteristic is sRGB, assume BT.709 primaries, would be quite odd otherwise. + // TODO(andreas): Other transfer characteristics may also hint at primaries. + ColorPrimaries::Bt709 + } else { + // Best guess: If the picture is 720p+ assume Bt709 because Rec709 + // is the "HDR" standard. + // TODO(#7594): 4k/UHD material should probably assume Bt2020? + // else if picture.height() >= 720 { + // ColorPrimaries::Bt709 + // } else { + // ColorPrimaries::Bt601 + // } + // + // This is also what the mpv player does (and probably others): + // https://wiki.x266.mov/docs/colorimetry/primaries#2-unspecified + // + // …then again, eyeballing VLC it looks like it just always assumes BT.709. + // The handwavy test case employed here was the same video in low & high resolution + // without specified primaries. Both looked the same. + ColorPrimaries::Bt709 + } } - } - rgba -} + dav1d::pixel::ColorPrimaries::BT709 => ColorPrimaries::Bt709, -fn i420_to_rgba(picture: &dav1d::Picture) -> Vec { - re_tracing::profile_function!(); - - let width = picture.width() as usize; - let height = picture.height() as usize; - let y_plane = picture.plane(PlanarImageComponent::Y); - let u_plane = picture.plane(PlanarImageComponent::U); - let v_plane = picture.plane(PlanarImageComponent::V); - let y_stride = picture.stride(PlanarImageComponent::Y) as usize; - let uv_stride = picture.stride(PlanarImageComponent::U) as usize; - - let mut rgba = vec![0u8; width * height * 4]; - - for y in 0..height { - for x in 0..width { - let y_value = y_plane[y * y_stride + x]; - let u_value = u_plane[(y / 2) * uv_stride + (x / 2)]; - let v_value = v_plane[(y / 2) * uv_stride + (x / 2)]; - let rgba_pixel = rgba_from_yuv(y_value, u_value, v_value); - - let offset = y * width * 4 + x * 4; - rgba[offset] = rgba_pixel[0]; - rgba[offset + 1] = rgba_pixel[1]; - rgba[offset + 2] = rgba_pixel[2]; - rgba[offset + 3] = rgba_pixel[3]; - } - } + // NTSC standard. Close enough to BT.601 for now. TODO(andreas): Is it worth warning? + dav1d::pixel::ColorPrimaries::BT470M => ColorPrimaries::Bt601, - rgba -} + // PAL standard. Close enough to BT.601 for now. TODO(andreas): Is it worth warning? + dav1d::pixel::ColorPrimaries::BT470BG => ColorPrimaries::Bt601, -fn i422_to_rgba(picture: &dav1d::Picture) -> Vec { - re_tracing::profile_function!(); - - let width = picture.width() as usize; - let height = picture.height() as usize; - let y_plane = picture.plane(PlanarImageComponent::Y); - let u_plane = picture.plane(PlanarImageComponent::U); - let v_plane = picture.plane(PlanarImageComponent::V); - let y_stride = picture.stride(PlanarImageComponent::Y) as usize; - let uv_stride = picture.stride(PlanarImageComponent::U) as usize; - - let mut rgba = vec![0u8; width * height * 4]; - - for y in 0..height { - for x in 0..width { - let y_value = y_plane[y * y_stride + x]; - let u_value = u_plane[y * uv_stride + (x / 2)]; - let v_value = v_plane[y * uv_stride + (x / 2)]; - let rgba_pixel = rgba_from_yuv(y_value, u_value, v_value); - - let offset = y * width * 4 + x * 4; - rgba[offset] = rgba_pixel[0]; - rgba[offset + 1] = rgba_pixel[1]; - rgba[offset + 2] = rgba_pixel[2]; - rgba[offset + 3] = rgba_pixel[3]; + // These are both using BT.2020 primaries. + dav1d::pixel::ColorPrimaries::ST170M | dav1d::pixel::ColorPrimaries::ST240M => { + ColorPrimaries::Bt601 } - } - rgba -} + // Is st428 also HDR? Not sure. + // BT2020 and P3 variants definitely are ;) + dav1d::pixel::ColorPrimaries::BT2020 + | dav1d::pixel::ColorPrimaries::ST428 + | dav1d::pixel::ColorPrimaries::P3DCI + | dav1d::pixel::ColorPrimaries::P3Display => { + // TODO(#7594): HDR support. + re_log::warn_once!("Video {debug_name:?} specified HDR color primaries. Rerun doesn't handle HDR colors correctly yet. Color artifacts may be visible."); + ColorPrimaries::Bt709 + } -fn i444_to_rgba(picture: &dav1d::Picture) -> Vec { - re_tracing::profile_function!(); - - let width = picture.width() as usize; - let height = picture.height() as usize; - let y_plane = picture.plane(PlanarImageComponent::Y); - let u_plane = picture.plane(PlanarImageComponent::U); - let v_plane = picture.plane(PlanarImageComponent::V); - let y_stride = picture.stride(PlanarImageComponent::Y) as usize; - let u_stride = picture.stride(PlanarImageComponent::U) as usize; - let v_stride = picture.stride(PlanarImageComponent::V) as usize; - - let mut rgba = vec![0u8; width * height * 4]; - - for y in 0..height { - for x in 0..width { - let y_value = y_plane[y * y_stride + x]; - let u_value = u_plane[y * u_stride + x]; - let v_value = v_plane[y * v_stride + x]; - let rgba_pixel = rgba_from_yuv(y_value, u_value, v_value); - - let offset = y * width * 4 + x * 4; - rgba[offset] = rgba_pixel[0]; - rgba[offset + 1] = rgba_pixel[1]; - rgba[offset + 2] = rgba_pixel[2]; - rgba[offset + 3] = rgba_pixel[3]; + dav1d::pixel::ColorPrimaries::Film | dav1d::pixel::ColorPrimaries::Tech3213 => { + re_log::warn_once!( + "Video {debug_name:?} specified unsupported color primaries {:?}. Color artifacts may be visible.", + picture.color_primaries() + ); + ColorPrimaries::Bt709 } } - - rgba } diff --git a/crates/store/re_video/src/decode/mod.rs b/crates/store/re_video/src/decode/mod.rs index 7fd77960f6de..77f641b41db9 100644 --- a/crates/store/re_video/src/decode/mod.rs +++ b/crates/store/re_video/src/decode/mod.rs @@ -59,7 +59,47 @@ pub struct Frame { pub duration: Time, } +/// Pixel format/layout used by [`Frame::data`]. +#[derive(Debug)] pub enum PixelFormat { Rgb8Unorm, Rgba8Unorm, + + Yuv { + layout: YuvPixelLayout, + range: YuvRange, + // TODO(andreas): color primaries should also apply to RGB data, + // but for now we just always assume RGB to be BT.709 ~= sRGB. + primaries: ColorPrimaries, + }, +} + +/// Pixel layout used by [`PixelFormat::Yuv`]. +/// +/// For details see `re_renderer`'s `YuvPixelLayout` type. +#[allow(non_camel_case_types)] +#[derive(Debug)] +pub enum YuvPixelLayout { + Y_U_V444, + Y_U_V422, + Y_U_V420, + Y400, +} + +/// Yuv value range used by [`PixelFormat::Yuv`]. +/// +/// For details see `re_renderer`'s `YuvRange` type. +#[derive(Debug)] +pub enum YuvRange { + Limited, + Full, +} + +/// Color primaries used by [`PixelFormat::Yuv`]. +/// +/// For details see `re_renderer`'s `ColorPrimaries` type. +#[derive(Debug)] +pub enum ColorPrimaries { + Bt601, + Bt709, } diff --git a/crates/viewer/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs b/crates/viewer/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs index 4652705d9b95..59e270458f4f 100644 --- a/crates/viewer/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs +++ b/crates/viewer/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs @@ -5,7 +5,7 @@ use crate::{ wgpu_resources::{BufferDesc, GpuBuffer, GpuBufferPool, GpuTexture}, }; -#[derive(thiserror::Error, Debug, PartialEq, Eq)] +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] pub enum CpuWriteGpuReadError { #[error("Attempting to allocate an empty buffer.")] ZeroSizeBufferAllocation, diff --git a/crates/viewer/re_renderer/src/renderer/mod.rs b/crates/viewer/re_renderer/src/renderer/mod.rs index 6ab0caec0d25..f29c19da86e3 100644 --- a/crates/viewer/re_renderer/src/renderer/mod.rs +++ b/crates/viewer/re_renderer/src/renderer/mod.rs @@ -50,7 +50,7 @@ pub trait DrawData { type Renderer: Renderer + Send + Sync; } -#[derive(thiserror::Error, Debug)] +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] pub enum DrawError { #[error(transparent)] Pool(#[from] PoolError), diff --git a/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs b/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs index 1ba94392a9ac..d0a2183887f1 100644 --- a/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs +++ b/crates/viewer/re_renderer/src/resource_managers/image_data_to_texture.rs @@ -60,7 +60,7 @@ pub enum SourceImageDataFormat { /// YUV (== `YCbCr`) formats, typically using chroma downsampling. Yuv { - format: YuvPixelLayout, + layout: YuvPixelLayout, primaries: ColorPrimaries, range: YuvRange, }, @@ -75,7 +75,7 @@ impl From for SourceImageDataFormat { } /// Error that can occur when converting image data to a texture. -#[derive(thiserror::Error, Debug)] +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] pub enum ImageDataToTextureError { #[error("Texture {0:?} has zero width or height!")] ZeroSize(DebugLabel), @@ -111,6 +111,20 @@ pub enum ImageDataToTextureError { #[error("Gpu-based conversion for texture {label:?} did not succeed: {err}")] GpuBasedConversionError { label: DebugLabel, err: DrawError }, + #[error("Texture {label:?} has invalid texture usage flags: {actual_usage:?}, expected at least {required_usage:?}")] + InvalidTargetTextureUsageFlags { + label: DebugLabel, + actual_usage: wgpu::TextureUsages, + required_usage: wgpu::TextureUsages, + }, + + #[error("Texture {label:?} has invalid texture format: {actual_format:?}, expected at least {required_format:?}")] + InvalidTargetTextureFormat { + label: DebugLabel, + actual_format: wgpu::TextureFormat, + required_format: wgpu::TextureFormat, + }, + // TODO(andreas): As we stop using `wgpu::TextureFormat` for input, this should become obsolete. #[error("Unsupported texture format {0:?}")] UnsupportedTextureFormat(wgpu::TextureFormat), @@ -120,6 +134,8 @@ pub enum ImageDataToTextureError { /// /// Arbitrary (potentially gpu based) conversions may be performed to upload the data to the GPU. pub struct ImageDataDesc<'a> { + /// If this desc is not used for a texture update, this label is used for the target texture. + /// Otherwise, it may still used for any intermediate resources that may be required during the conversion process. pub label: DebugLabel, /// Data for the highest mipmap level. @@ -141,7 +157,11 @@ pub struct ImageDataDesc<'a> { } impl<'a> ImageDataDesc<'a> { - fn validate(&self, limits: &wgpu::Limits) -> Result<(), ImageDataToTextureError> { + fn validate( + &self, + limits: &wgpu::Limits, + target_texture_desc: &TextureDesc, + ) -> Result<(), ImageDataToTextureError> { let Self { label, data, @@ -149,6 +169,24 @@ impl<'a> ImageDataDesc<'a> { width_height, } = self; + if !target_texture_desc + .usage + .contains(self.target_texture_usage_requirements()) + { + return Err(ImageDataToTextureError::InvalidTargetTextureUsageFlags { + label: target_texture_desc.label.clone(), + actual_usage: target_texture_desc.usage, + required_usage: self.target_texture_usage_requirements(), + }); + } + if target_texture_desc.format != self.target_texture_format() { + return Err(ImageDataToTextureError::InvalidTargetTextureFormat { + label: target_texture_desc.label.clone(), + actual_format: target_texture_desc.format, + required_format: self.target_texture_format(), + }); + } + if width_height[0] == 0 || width_height[1] == 0 { return Err(ImageDataToTextureError::ZeroSize(label.clone())); } @@ -173,7 +211,7 @@ impl<'a> ImageDataDesc<'a> { .ok_or(ImageDataToTextureError::UnsupportedTextureFormat(*format))? as usize } - SourceImageDataFormat::Yuv { format, .. } => { + SourceImageDataFormat::Yuv { layout: format, .. } => { format.num_data_buffer_bytes(*width_height) } }; @@ -189,6 +227,48 @@ impl<'a> ImageDataDesc<'a> { Ok(()) } + + /// The texture usages required in order to store this image data. + pub fn target_texture_usage_requirements(&self) -> wgpu::TextureUsages { + match self.format { + SourceImageDataFormat::WgpuCompatible(_) => wgpu::TextureUsages::COPY_DST, // Data arrives via raw data copy. + SourceImageDataFormat::Yuv { .. } => { + YuvFormatConversionTask::REQUIRED_TARGET_TEXTURE_USAGE_FLAGS + } + } + } + + /// The texture format required in order to store this image data. + pub fn target_texture_format(&self) -> wgpu::TextureFormat { + match self.format { + SourceImageDataFormat::WgpuCompatible(format) => format, + SourceImageDataFormat::Yuv { .. } => YuvFormatConversionTask::OUTPUT_FORMAT, + } + } + + /// Creates a texture that can hold the image data. + pub fn create_target_texture( + &self, + ctx: &RenderContext, + texture_usages: wgpu::TextureUsages, + ) -> GpuTexture { + ctx.gpu_resources.textures.alloc( + &ctx.device, + &TextureDesc { + label: self.label.clone(), + size: wgpu::Extent3d { + width: self.width_height[0], + height: self.width_height[1], + depth_or_array_layers: 1, + }, + mip_level_count: 1, // No mipmapping support yet. + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: self.target_texture_format(), + usage: self.target_texture_usage_requirements() | texture_usages, + }, + ) + } } /// Takes raw image data and transfers & converts it to a GPU texture. @@ -206,10 +286,11 @@ impl<'a> ImageDataDesc<'a> { pub fn transfer_image_data_to_texture( ctx: &RenderContext, image_data: ImageDataDesc<'_>, -) -> Result { + target_texture: &GpuTexture, +) -> Result<(), ImageDataToTextureError> { re_tracing::profile_function!(); - image_data.validate(&ctx.device.limits())?; + image_data.validate(&ctx.device.limits(), &target_texture.creation_desc)?; let ImageDataDesc { label, @@ -222,13 +303,13 @@ pub fn transfer_image_data_to_texture( // Reminder: We can't use raw buffers because of WebGL compatibility. let [data_texture_width, data_texture_height] = match source_format { SourceImageDataFormat::WgpuCompatible(_) => output_width_height, - SourceImageDataFormat::Yuv { format, .. } => { - format.data_texture_width_height(output_width_height) + SourceImageDataFormat::Yuv { layout, .. } => { + layout.data_texture_width_height(output_width_height) } }; let data_texture_format = match source_format { SourceImageDataFormat::WgpuCompatible(format) => format, - SourceImageDataFormat::Yuv { format, .. } => format.data_texture_format(), + SourceImageDataFormat::Yuv { layout, .. } => layout.data_texture_format(), }; // Allocate gpu belt data and upload it. @@ -236,53 +317,58 @@ pub fn transfer_image_data_to_texture( SourceImageDataFormat::WgpuCompatible(_) => label.clone(), SourceImageDataFormat::Yuv { .. } => format!("{label}_source_data").into(), }; - let data_texture = ctx.gpu_resources.textures.alloc( - &ctx.device, - &TextureDesc { - label: data_texture_label, - size: wgpu::Extent3d { - width: data_texture_width, - height: data_texture_height, - depth_or_array_layers: 1, + + let data_texture = match source_format { + // Needs intermediate data texture. + SourceImageDataFormat::Yuv { .. } => ctx.gpu_resources.textures.alloc( + &ctx.device, + &TextureDesc { + label: data_texture_label, + size: wgpu::Extent3d { + width: data_texture_width, + height: data_texture_height, + depth_or_array_layers: 1, + }, + mip_level_count: 1, // We don't have mipmap level generation yet! + sample_count: 1, + dimension: wgpu::TextureDimension::D2, + format: data_texture_format, + usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, }, - mip_level_count: 1, // We don't have mipmap level generation yet! - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: data_texture_format, - usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - }, - ); + ), + + // Target is directly written to. + SourceImageDataFormat::WgpuCompatible(_) => target_texture.clone(), + }; + copy_data_to_texture(ctx, &data_texture, data.as_ref())?; // Build a converter task, feeding in the raw data. let converter_task = match source_format { SourceImageDataFormat::WgpuCompatible(_) => { // No further conversion needed, we're done here! - return Ok(data_texture); + return Ok(()); } SourceImageDataFormat::Yuv { - format, + layout, primaries, range, } => YuvFormatConversionTask::new( ctx, - format, + layout, range, primaries, &data_texture, - &label, - output_width_height, + target_texture, ), }; // Once there's different gpu based conversions, we should probably trait-ify this so we can keep the basic steps. // Note that we execute the task right away, but the way things are set up (by means of using the `Renderer` framework) // it would be fairly easy to schedule this differently! - let output_texture = converter_task + converter_task .convert_input_data_to_texture(ctx) - .map_err(|err| ImageDataToTextureError::GpuBasedConversionError { label, err })?; - - Ok(output_texture) + .map_err(|err| ImageDataToTextureError::GpuBasedConversionError { label, err }) } fn copy_data_to_texture( diff --git a/crates/viewer/re_renderer/src/resource_managers/mod.rs b/crates/viewer/re_renderer/src/resource_managers/mod.rs index c3210fc9e034..5f62146856b8 100644 --- a/crates/viewer/re_renderer/src/resource_managers/mod.rs +++ b/crates/viewer/re_renderer/src/resource_managers/mod.rs @@ -11,7 +11,8 @@ mod texture_manager; mod yuv_converter; pub use image_data_to_texture::{ - ColorPrimaries, ImageDataDesc, ImageDataToTextureError, SourceImageDataFormat, + transfer_image_data_to_texture, ColorPrimaries, ImageDataDesc, ImageDataToTextureError, + SourceImageDataFormat, }; pub use texture_manager::{GpuTexture2D, TextureManager2D, TextureManager2DError}; pub use yuv_converter::{YuvPixelLayout, YuvRange}; diff --git a/crates/viewer/re_renderer/src/resource_managers/texture_manager.rs b/crates/viewer/re_renderer/src/resource_managers/texture_manager.rs index 0ed8b37eebaf..5caa15dac09e 100644 --- a/crates/viewer/re_renderer/src/resource_managers/texture_manager.rs +++ b/crates/viewer/re_renderer/src/resource_managers/texture_manager.rs @@ -229,10 +229,10 @@ impl TextureManager2D { // Currently we don't store any data in the texture manager. // In the future we might handle (lazy?) mipmap generation in here or keep track of lazy upload processing. - Ok(GpuTexture2D(transfer_image_data_to_texture( - render_ctx, - creation_desc, - )?)) + let texture = + creation_desc.create_target_texture(render_ctx, wgpu::TextureUsages::TEXTURE_BINDING); + transfer_image_data_to_texture(render_ctx, creation_desc, &texture)?; + Ok(GpuTexture2D(texture)) } /// Creates a new 2D texture resource and schedules data upload to the GPU if a texture @@ -277,11 +277,11 @@ impl TextureManager2D { // Run potentially expensive texture creation code: let tex_creation_desc = try_create_texture_desc() .map_err(|err| TextureManager2DError::DataCreation(err))?; - let texture = GpuTexture2D(transfer_image_data_to_texture( - render_ctx, - tex_creation_desc, - )?); - entry.insert(texture).clone() + + let texture = tex_creation_desc + .create_target_texture(render_ctx, wgpu::TextureUsages::TEXTURE_BINDING); + transfer_image_data_to_texture(render_ctx, tex_creation_desc, &texture)?; + entry.insert(GpuTexture2D(texture)).clone() } }; diff --git a/crates/viewer/re_renderer/src/resource_managers/yuv_converter.rs b/crates/viewer/re_renderer/src/resource_managers/yuv_converter.rs index 075c24f13ccb..9aea41c22b29 100644 --- a/crates/viewer/re_renderer/src/resource_managers/yuv_converter.rs +++ b/crates/viewer/re_renderer/src/resource_managers/yuv_converter.rs @@ -6,9 +6,9 @@ use crate::{ renderer::{screen_triangle_vertex_shader, DrawData, DrawError, Renderer}, wgpu_resources::{ BindGroupDesc, BindGroupEntry, BindGroupLayoutDesc, GpuBindGroup, GpuBindGroupLayoutHandle, - GpuRenderPipelineHandle, GpuTexture, PipelineLayoutDesc, RenderPipelineDesc, TextureDesc, + GpuRenderPipelineHandle, GpuTexture, PipelineLayoutDesc, RenderPipelineDesc, }, - DebugLabel, RenderContext, + RenderContext, }; use super::ColorPrimaries; @@ -276,12 +276,18 @@ impl DrawData for YuvFormatConversionTask { } impl YuvFormatConversionTask { + /// Format that a target texture must have in order to be used as output of this converter. + /// /// sRGB encoded 8 bit texture. /// /// Not using [`wgpu::TextureFormat::Rgba8UnormSrgb`] since consumers typically consume this /// texture with software EOTF ("to linear") for more flexibility. pub const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8Unorm; + /// Usage flags that a target texture must have in order to be used as output of this converter. + pub const REQUIRED_TARGET_TEXTURE_USAGE_FLAGS: wgpu::TextureUsages = + wgpu::TextureUsages::RENDER_ATTACHMENT; + /// Creates a new conversion task that can be used with [`YuvFormatConverter`]. /// /// Does *not* validate that the input data has the expected format, @@ -292,37 +298,21 @@ impl YuvFormatConversionTask { yuv_range: YuvRange, primaries: ColorPrimaries, input_data: &GpuTexture, - output_label: &DebugLabel, - output_width_height: [u32; 2], + target_texture: &GpuTexture, ) -> Self { - let target_texture = ctx.gpu_resources.textures.alloc( - &ctx.device, - &TextureDesc { - label: output_label.clone(), - size: wgpu::Extent3d { - width: output_width_height[0], - height: output_width_height[1], - depth_or_array_layers: 1, - }, - mip_level_count: 1, // We don't have mipmap level generation yet! - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: Self::OUTPUT_FORMAT, - usage: wgpu::TextureUsages::TEXTURE_BINDING - | wgpu::TextureUsages::COPY_DST - | wgpu::TextureUsages::RENDER_ATTACHMENT, - }, - ); - + let target_label = target_texture.creation_desc.label.clone(); let renderer = ctx.renderer::(); let uniform_buffer = create_and_fill_uniform_buffer( ctx, - format!("{output_label}_conversion").into(), + format!("{target_label}_conversion").into(), gpu_data::UniformBuffer { yuv_layout: yuv_layout as _, primaries: primaries as _, - target_texture_size: output_width_height, + target_texture_size: [ + target_texture.creation_desc.size.width, + target_texture.creation_desc.size.height, + ], yuv_range: (yuv_range as u32).into(), _end_padding: Default::default(), @@ -344,15 +334,12 @@ impl YuvFormatConversionTask { Self { bind_group, - target_texture, + target_texture: target_texture.clone(), } } /// Runs the conversion from the input texture data. - pub fn convert_input_data_to_texture( - self, - ctx: &RenderContext, - ) -> Result { + pub fn convert_input_data_to_texture(self, ctx: &RenderContext) -> Result<(), DrawError> { // TODO(andreas): Does this have to be on the global view encoder? // If this ever becomes a problem we could easily schedule this to another encoder as long as // we guarantee that the conversion is enqueued before the resulting texture is used. @@ -378,9 +365,7 @@ impl YuvFormatConversionTask { crate::draw_phases::DrawPhase::Opaque, // Don't care about the phase. &mut pass, &self, - )?; - - Ok(self.target_texture) + ) } } diff --git a/crates/viewer/re_renderer/src/video/decoder/mod.rs b/crates/viewer/re_renderer/src/video/decoder/mod.rs index cf5add19a795..c62c58857c64 100644 --- a/crates/viewer/re_renderer/src/video/decoder/mod.rs +++ b/crates/viewer/re_renderer/src/video/decoder/mod.rs @@ -139,7 +139,7 @@ impl VideoDecoder { if cfg!(debug_assertions) { return Err(DecodingError::NoNativeDebug); // because debug builds of rav1d are EXTREMELY slow } else { - let av1_decoder = re_video::decode::av1::SyncDav1dDecoder::new() + let av1_decoder = re_video::decode::av1::SyncDav1dDecoder::new(debug_name.clone()) .map_err(|err| DecodingError::StartDecoder(err.to_string()))?; let decoder = native_decoder::NativeDecoder::new(debug_name, Box::new(av1_decoder))?; diff --git a/crates/viewer/re_renderer/src/video/decoder/native_decoder.rs b/crates/viewer/re_renderer/src/video/decoder/native_decoder.rs index a02cb4fbf807..fccdb1fe13ec 100644 --- a/crates/viewer/re_renderer/src/video/decoder/native_decoder.rs +++ b/crates/viewer/re_renderer/src/video/decoder/native_decoder.rs @@ -6,7 +6,15 @@ use re_video::{Chunk, Frame, Time}; use parking_lot::Mutex; -use crate::{video::DecodingError, RenderContext}; +use crate::{ + resource_managers::{ + transfer_image_data_to_texture, ColorPrimaries, ImageDataDesc, SourceImageDataFormat, + YuvPixelLayout, YuvRange, + }, + video::DecodingError, + wgpu_resources::GpuTexture, + RenderContext, +}; use super::{latest_at_idx, TimedDecodingError, VideoChunkDecoder, VideoTexture}; @@ -100,7 +108,7 @@ impl VideoChunkDecoder for NativeDecoder { if frame_time_range.contains(&presentation_timestamp) && video_texture.time_range != frame_time_range { - copy_video_frame_to_texture(&render_ctx.queue, frame, &video_texture.texture.texture)?; + copy_video_frame_to_texture(render_ctx, frame, &video_texture.texture)?; video_texture.time_range = frame_time_range; } @@ -125,58 +133,71 @@ impl VideoChunkDecoder for NativeDecoder { } fn copy_video_frame_to_texture( - queue: &wgpu::Queue, + ctx: &RenderContext, frame: &Frame, - texture: &wgpu::Texture, + target_texture: &GpuTexture, ) -> Result<(), DecodingError> { let format = match frame.format { re_video::PixelFormat::Rgb8Unorm => { + // TODO(andreas): `ImageDataDesc` should have RGB handling! return copy_video_frame_to_texture( - queue, + ctx, &Frame { data: crate::pad_rgb_to_rgba(&frame.data, 255_u8), format: re_video::PixelFormat::Rgba8Unorm, ..*frame }, - texture, + target_texture, ); } - - re_video::PixelFormat::Rgba8Unorm => wgpu::TextureFormat::Rgba8Unorm, + re_video::PixelFormat::Rgba8Unorm | re_video::PixelFormat::Yuv { .. } => { + wgpu::TextureFormat::Rgba8Unorm + } }; re_tracing::profile_function!(); - let size = wgpu::Extent3d { - width: frame.width, - height: frame.height, - depth_or_array_layers: 1, - }; - - let width_blocks = frame.width / format.block_dimensions().0; - - #[allow(clippy::unwrap_used)] // block_copy_size can only fail for weird compressed formats - let block_size = format - .block_copy_size(Some(wgpu::TextureAspect::All)) - .unwrap(); + let format = match &frame.format { + re_video::PixelFormat::Rgb8Unorm => { + unreachable!("Handled explicitly earlier in this function"); + } - let bytes_per_row_unaligned = width_blocks * block_size; + re_video::PixelFormat::Rgba8Unorm => { + SourceImageDataFormat::WgpuCompatible(wgpu::TextureFormat::Rgba8Unorm) + } - queue.write_texture( - wgpu::ImageCopyTexture { - texture, - mip_level: 0, - origin: wgpu::Origin3d::ZERO, - aspect: wgpu::TextureAspect::All, + re_video::PixelFormat::Yuv { + layout, + range, + primaries, + } => SourceImageDataFormat::Yuv { + layout: match layout { + re_video::decode::YuvPixelLayout::Y_U_V444 => YuvPixelLayout::Y_U_V444, + re_video::decode::YuvPixelLayout::Y_U_V422 => YuvPixelLayout::Y_U_V422, + re_video::decode::YuvPixelLayout::Y_U_V420 => YuvPixelLayout::Y_U_V420, + re_video::decode::YuvPixelLayout::Y400 => YuvPixelLayout::Y400, + }, + primaries: match primaries { + re_video::decode::ColorPrimaries::Bt601 => ColorPrimaries::Bt601, + re_video::decode::ColorPrimaries::Bt709 => ColorPrimaries::Bt709, + }, + range: match range { + re_video::decode::YuvRange::Limited => YuvRange::Limited, + re_video::decode::YuvRange::Full => YuvRange::Full, + }, }, - &frame.data, - wgpu::ImageDataLayout { - offset: 0, - bytes_per_row: Some(bytes_per_row_unaligned), - rows_per_image: None, + }; + + transfer_image_data_to_texture( + ctx, + ImageDataDesc { + label: "video_texture_upload".into(), + data: std::borrow::Cow::Borrowed(frame.data.as_slice()), + format, + width_height: [frame.width, frame.height], }, - size, - ); + target_texture, + )?; Ok(()) } diff --git a/crates/viewer/re_renderer/src/video/mod.rs b/crates/viewer/re_renderer/src/video/mod.rs index 659fed6131e5..c60d6fce3cbc 100644 --- a/crates/viewer/re_renderer/src/video/mod.rs +++ b/crates/viewer/re_renderer/src/video/mod.rs @@ -60,6 +60,9 @@ pub enum DecodingError { #[cfg(not(target_arch = "wasm32"))] #[error("Native video decoding not supported in native debug builds.")] NoNativeDebug, + + #[error("Failed to create gpu texture from decoded video data: {0}")] + ImageDataToTextureError(#[from] crate::resource_managers::ImageDataToTextureError), } pub type FrameDecodingResult = Result; diff --git a/crates/viewer/re_renderer/src/wgpu_resources/resource.rs b/crates/viewer/re_renderer/src/wgpu_resources/resource.rs index b6ed1645a7fd..e7c345babcf9 100644 --- a/crates/viewer/re_renderer/src/wgpu_resources/resource.rs +++ b/crates/viewer/re_renderer/src/wgpu_resources/resource.rs @@ -1,6 +1,6 @@ use std::sync::atomic::AtomicU64; -#[derive(thiserror::Error, Debug, PartialEq, Eq)] +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] pub enum PoolError { #[error("Requested resource isn't available because the handle is no longer valid")] ResourceNotAvailable, diff --git a/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs b/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs index ba6f0907fb2e..41f5c2e3983f 100644 --- a/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs +++ b/crates/viewer/re_viewer_context/src/gpu_bridge/image_to_gpu.rs @@ -267,7 +267,7 @@ pub fn texture_creation_desc_from_color_image<'a>( // PixelFormat::Y_U_V24_FullRange | PixelFormat::Y_U_V24_LimitedRange => { SourceImageDataFormat::Yuv { - format: YuvPixelLayout::Y_U_V444, + layout: YuvPixelLayout::Y_U_V444, range, primaries, } @@ -275,7 +275,7 @@ pub fn texture_creation_desc_from_color_image<'a>( PixelFormat::Y_U_V16_FullRange | PixelFormat::Y_U_V16_LimitedRange => { SourceImageDataFormat::Yuv { - format: YuvPixelLayout::Y_U_V422, + layout: YuvPixelLayout::Y_U_V422, range, primaries, } @@ -283,7 +283,7 @@ pub fn texture_creation_desc_from_color_image<'a>( PixelFormat::Y_U_V12_FullRange | PixelFormat::Y_U_V12_LimitedRange => { SourceImageDataFormat::Yuv { - format: YuvPixelLayout::Y_U_V420, + layout: YuvPixelLayout::Y_U_V420, range, primaries, } @@ -291,20 +291,20 @@ pub fn texture_creation_desc_from_color_image<'a>( PixelFormat::Y8_FullRange | PixelFormat::Y8_LimitedRange => { SourceImageDataFormat::Yuv { - format: YuvPixelLayout::Y400, + layout: YuvPixelLayout::Y400, range, primaries, } } PixelFormat::NV12 => SourceImageDataFormat::Yuv { - format: YuvPixelLayout::Y_UV420, + layout: YuvPixelLayout::Y_UV420, range, primaries, }, PixelFormat::YUY2 => SourceImageDataFormat::Yuv { - format: YuvPixelLayout::YUYV422, + layout: YuvPixelLayout::YUYV422, range, primaries, }, From 0045de54a3599060f0a11369dcfac7957b2d6bdb Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Fri, 11 Oct 2024 11:59:22 -0400 Subject: [PATCH 15/33] Allow component selectors to be specified as strings with flexible matching (#7695) ### What - Resolves: https://github.com/rerun-io/rerun/issues/7629 - We also do this promotion for the ComponentLike in the view contents expression on the python side This means you can now do: ``` view = self.recording.view(index="my_index", contents={"points": "position3D"}).select("position3d") ``` ### Checklist * [x] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [x] I've included a screenshot or gif (if applicable) * [x] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7695?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7695?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7695) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Clement Rey --- crates/store/re_chunk_store/src/dataframe.rs | 54 ++++++++++++++----- crates/store/re_dataframe/src/query.rs | 34 ++++++------ .../component_column_selector_ext.rs | 5 +- .../component_column_selector_ext.rs | 7 ++- crates/store/re_types_core/src/loggable.rs | 9 ++++ .../src/view_query/blueprint.rs | 15 +++--- rerun_py/src/dataframe.rs | 36 ++++++++++--- rerun_py/tests/unit/test_dataframe.py | 25 +++++---- 8 files changed, 124 insertions(+), 61 deletions(-) diff --git a/crates/store/re_chunk_store/src/dataframe.rs b/crates/store/re_chunk_store/src/dataframe.rs index 10433e05e1af..42c6a33e0082 100644 --- a/crates/store/re_chunk_store/src/dataframe.rs +++ b/crates/store/re_chunk_store/src/dataframe.rs @@ -278,8 +278,8 @@ impl std::fmt::Display for ComponentColumnDescriptor { impl ComponentColumnDescriptor { #[inline] - pub fn matches(&self, entity_path: &EntityPath, component_name: &ComponentName) -> bool { - &self.entity_path == entity_path && &self.component_name == component_name + pub fn matches(&self, entity_path: &EntityPath, component_name: &str) -> bool { + &self.entity_path == entity_path && self.component_name.matches(component_name) } fn metadata(&self) -> arrow2::datatypes::Metadata { @@ -422,9 +422,10 @@ pub struct ComponentColumnSelector { pub entity_path: EntityPath, /// Semantic name associated with this data. - // - // TODO(cmc): this should be `component_name`. - pub component: ComponentName, + /// + /// This string will be flexibly matched against the available component names. + /// Valid matches are case invariant matches of either the full name or the short name. + pub component_name: String, /// How to join the data into the `RecordBatch`. // @@ -437,7 +438,7 @@ impl From for ComponentColumnSelector { fn from(desc: ComponentColumnDescriptor) -> Self { Self { entity_path: desc.entity_path.clone(), - component: desc.component_name, + component_name: desc.component_name.to_string(), join_encoding: desc.join_encoding, } } @@ -449,17 +450,17 @@ impl ComponentColumnSelector { pub fn new(entity_path: EntityPath) -> Self { Self { entity_path, - component: C::name(), + component_name: C::name().to_string(), join_encoding: JoinEncoding::default(), } } /// Select a component based on its [`EntityPath`] and [`ComponentName`]. #[inline] - pub fn new_for_component_name(entity_path: EntityPath, component: ComponentName) -> Self { + pub fn new_for_component_name(entity_path: EntityPath, component_name: ComponentName) -> Self { Self { entity_path, - component, + component_name: component_name.to_string(), join_encoding: JoinEncoding::default(), } } @@ -476,11 +477,11 @@ impl std::fmt::Display for ComponentColumnSelector { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { entity_path, - component, + component_name, join_encoding: _, } = self; - f.write_fmt(format_args!("{entity_path}@{}", component.short_name())) + f.write_fmt(format_args!("{entity_path}:{component_name}")) } } @@ -793,13 +794,38 @@ impl ChunkStore { &self, selector: &ComponentColumnSelector, ) -> ComponentColumnDescriptor { + // Happy path if this string is a valid component + // TODO(#7699) This currently interns every string ever queried which could be wasteful, especially + // in long-running servers. In practice this probably doesn't matter. + let direct_component = ComponentName::from(selector.component_name.clone()); + + let component_name = if self.all_components().contains(&direct_component) { + direct_component + } else { + self.all_components_for_entity(&selector.entity_path) + // First just check on the entity since this is the most likely place to find it. + .and_then(|components| { + components + .into_iter() + .find(|component_name| component_name.matches(&selector.component_name)) + }) + // Fall back on matching any component in the store + .or_else(|| { + self.all_components() + .into_iter() + .find(|component_name| component_name.matches(&selector.component_name)) + }) + // Finally fall back on the direct component name + .unwrap_or(direct_component) + }; + let ColumnMetadata { is_static, is_indicator, is_tombstone, is_semantically_empty, } = self - .lookup_column_metadata(&selector.entity_path, &selector.component) + .lookup_column_metadata(&selector.entity_path, &component_name) .unwrap_or(ColumnMetadata { is_static: false, is_indicator: false, @@ -808,7 +834,7 @@ impl ChunkStore { }); let datatype = self - .lookup_datatype(&selector.component) + .lookup_datatype(&component_name) .cloned() .unwrap_or_else(|| ArrowDatatype::Null); @@ -816,7 +842,7 @@ impl ChunkStore { entity_path: selector.entity_path.clone(), archetype_name: None, archetype_field_name: None, - component_name: selector.component, + component_name, store_datatype: ArrowListArray::::default_datatype(datatype.clone()), join_encoding: selector.join_encoding, is_static, diff --git a/crates/store/re_dataframe/src/query.rs b/crates/store/re_dataframe/src/query.rs index 2eb70680b956..96dc02798b79 100644 --- a/crates/store/re_dataframe/src/query.rs +++ b/crates/store/re_dataframe/src/query.rs @@ -351,7 +351,7 @@ impl QueryHandle<'_> { ColumnSelector::Component(selected_column) => { let ComponentColumnSelector { entity_path: selected_entity_path, - component: selected_component_name, + component_name: selected_component_name, join_encoding: _, } = selected_column; @@ -364,7 +364,7 @@ impl QueryHandle<'_> { }) .find(|(_idx, view_descr)| { view_descr.entity_path == *selected_entity_path - && view_descr.component_name == *selected_component_name + && view_descr.component_name.matches(selected_component_name) }) .map_or_else( || { @@ -374,7 +374,9 @@ impl QueryHandle<'_> { entity_path: selected_entity_path.clone(), archetype_name: None, archetype_field_name: None, - component_name: *selected_component_name, + component_name: ComponentName::from( + selected_component_name.clone(), + ), store_datatype: arrow2::datatypes::DataType::Null, join_encoding: JoinEncoding::default(), is_static: false, @@ -418,7 +420,7 @@ impl QueryHandle<'_> { if let Some(pov) = self.query.filtered_point_of_view.as_ref() { if pov.entity_path == column.entity_path - && pov.component == column.component_name + && column.component_name.matches(&pov.component_name) { view_pov_chunks_idx = Some(idx); } @@ -1437,7 +1439,7 @@ mod tests { let mut query = QueryExpression::new(timeline); query.filtered_point_of_view = Some(ComponentColumnSelector { entity_path: "no/such/entity".into(), - component: MyPoint::name(), + component_name: MyPoint::name().to_string(), join_encoding: Default::default(), }); eprintln!("{query:#?}:"); @@ -1464,7 +1466,7 @@ mod tests { let mut query = QueryExpression::new(timeline); query.filtered_point_of_view = Some(ComponentColumnSelector { entity_path: entity_path.clone(), - component: "AComponentColumnThatDoesntExist".into(), + component_name: "AComponentColumnThatDoesntExist".into(), join_encoding: Default::default(), }); eprintln!("{query:#?}:"); @@ -1491,7 +1493,7 @@ mod tests { let mut query = QueryExpression::new(timeline); query.filtered_point_of_view = Some(ComponentColumnSelector { entity_path: entity_path.clone(), - component: MyPoint::name(), + component_name: MyPoint::name().to_string(), join_encoding: Default::default(), }); eprintln!("{query:#?}:"); @@ -1528,7 +1530,7 @@ mod tests { let mut query = QueryExpression::new(timeline); query.filtered_point_of_view = Some(ComponentColumnSelector { entity_path: entity_path.clone(), - component: MyColor::name(), + component_name: MyColor::name().to_string(), join_encoding: Default::default(), }); eprintln!("{query:#?}:"); @@ -1739,22 +1741,22 @@ mod tests { query.selection = Some(vec![ ColumnSelector::Component(ComponentColumnSelector { entity_path: entity_path.clone(), - component: MyColor::name(), + component_name: MyColor::name().to_string(), join_encoding: Default::default(), }), ColumnSelector::Component(ComponentColumnSelector { entity_path: entity_path.clone(), - component: MyColor::name(), + component_name: MyColor::name().to_string(), join_encoding: Default::default(), }), ColumnSelector::Component(ComponentColumnSelector { entity_path: "non_existing_entity".into(), - component: MyColor::name(), + component_name: MyColor::name().to_string(), join_encoding: Default::default(), }), ColumnSelector::Component(ComponentColumnSelector { entity_path: entity_path.clone(), - component: "AComponentColumnThatDoesntExist".into(), + component_name: "AComponentColumnThatDoesntExist".into(), join_encoding: Default::default(), }), ]); @@ -1828,17 +1830,17 @@ mod tests { // ColumnSelector::Component(ComponentColumnSelector { entity_path: entity_path.clone(), - component: MyPoint::name(), + component_name: MyPoint::name().to_string(), join_encoding: Default::default(), }), ColumnSelector::Component(ComponentColumnSelector { entity_path: entity_path.clone(), - component: MyColor::name(), + component_name: MyColor::name().to_string(), join_encoding: Default::default(), }), ColumnSelector::Component(ComponentColumnSelector { entity_path: entity_path.clone(), - component: MyLabel::name(), + component_name: MyLabel::name().to_string(), join_encoding: Default::default(), }), ]); @@ -2020,7 +2022,7 @@ mod tests { let mut query = QueryExpression::new(timeline); query.filtered_point_of_view = Some(ComponentColumnSelector { entity_path: entity_path.clone(), - component: MyPoint::name(), + component_name: MyPoint::name().to_string(), join_encoding: Default::default(), }); eprintln!("{query:#?}:"); diff --git a/crates/store/re_types/src/blueprint/components/component_column_selector_ext.rs b/crates/store/re_types/src/blueprint/components/component_column_selector_ext.rs index 18957e74b779..c6a88aca9307 100644 --- a/crates/store/re_types/src/blueprint/components/component_column_selector_ext.rs +++ b/crates/store/re_types/src/blueprint/components/component_column_selector_ext.rs @@ -1,9 +1,8 @@ use re_log_types::EntityPath; -use re_types_core::ComponentName; impl super::ComponentColumnSelector { - /// Create a [`Self`] from an [`EntityPath`] and a [`ComponentName`]. - pub fn new(entity_path: &EntityPath, component_name: ComponentName) -> Self { + /// Create a [`Self`] from an [`EntityPath`] and a [`re_types_core::ComponentName`] expressed as string. + pub fn new(entity_path: &EntityPath, component_name: &str) -> Self { crate::blueprint::datatypes::ComponentColumnSelector::new(entity_path, component_name) .into() } diff --git a/crates/store/re_types/src/blueprint/datatypes/component_column_selector_ext.rs b/crates/store/re_types/src/blueprint/datatypes/component_column_selector_ext.rs index ca74f5fc2a04..0f63362a38f1 100644 --- a/crates/store/re_types/src/blueprint/datatypes/component_column_selector_ext.rs +++ b/crates/store/re_types/src/blueprint/datatypes/component_column_selector_ext.rs @@ -1,12 +1,11 @@ use re_log_types::EntityPath; -use re_types_core::ComponentName; impl super::ComponentColumnSelector { - /// Create a [`Self`] from an [`EntityPath`] and a [`ComponentName`]. - pub fn new(entity_path: &EntityPath, component_name: ComponentName) -> Self { + /// Create a [`Self`] from an [`EntityPath`] and a [`re_types_core::ComponentName`] expressed as string. + pub fn new(entity_path: &EntityPath, component_name: &str) -> Self { Self { entity_path: entity_path.into(), - component: component_name.as_str().into(), + component: component_name.into(), } } } diff --git a/crates/store/re_types_core/src/loggable.rs b/crates/store/re_types_core/src/loggable.rs index cacb8400960a..9889be90aeef 100644 --- a/crates/store/re_types_core/src/loggable.rs +++ b/crates/store/re_types_core/src/loggable.rs @@ -184,6 +184,15 @@ impl ComponentName { None // A user component } } + + /// Determine if component matches a string + /// + /// Valid matches are case invariant matches of either the full name or the short name. + pub fn matches(&self, other: &str) -> bool { + self.0.as_str() == other + || self.full_name().to_lowercase() == other.to_lowercase() + || self.short_name().to_lowercase() == other.to_lowercase() + } } // --- diff --git a/crates/viewer/re_space_view_dataframe/src/view_query/blueprint.rs b/crates/viewer/re_space_view_dataframe/src/view_query/blueprint.rs index 17fa3dd4725d..36dabf2911bb 100644 --- a/crates/viewer/re_space_view_dataframe/src/view_query/blueprint.rs +++ b/crates/viewer/re_space_view_dataframe/src/view_query/blueprint.rs @@ -133,13 +133,15 @@ impl Query { .push(desc.timeline.as_str().into()); } - ColumnSelector::Component(desc) => { - let blueprint_component_descriptor = - datatypes::ComponentColumnSelector::new(&desc.entity_path, desc.component); + ColumnSelector::Component(selector) => { + let blueprint_component_selector = datatypes::ComponentColumnSelector::new( + &selector.entity_path, + &selector.component_name, + ); selected_columns .component_columns - .push(blueprint_component_descriptor); + .push(blueprint_component_selector); } } } @@ -257,8 +259,9 @@ impl Query { component_name, } => { selected_columns.retain(|column| match column { - ColumnSelector::Component(desc) => { - desc.entity_path != entity_path || desc.component != component_name + ColumnSelector::Component(selector) => { + selector.entity_path != entity_path + || !component_name.matches(&selector.component_name) } ColumnSelector::Time(_) => true, }); diff --git a/rerun_py/src/dataframe.rs b/rerun_py/src/dataframe.rs index 00c573c9d964..9109dc77adc7 100644 --- a/rerun_py/src/dataframe.rs +++ b/rerun_py/src/dataframe.rs @@ -133,7 +133,7 @@ impl PyComponentColumnSelector { fn new(entity_path: &str, component_name: ComponentLike) -> Self { Self(ComponentColumnSelector { entity_path: entity_path.into(), - component: component_name.0, + component_name: component_name.0, join_encoding: Default::default(), }) } @@ -149,8 +149,7 @@ impl PyComponentColumnSelector { fn __repr__(&self) -> String { format!( "Component({}:{})", - self.0.entity_path, - self.0.component.short_name() + self.0.entity_path, self.0.component_name ) } } @@ -298,19 +297,19 @@ impl<'py> IndexValuesLike<'py> { } } -struct ComponentLike(re_sdk::ComponentName); +struct ComponentLike(String); impl FromPyObject<'_> for ComponentLike { fn extract_bound(component: &Bound<'_, PyAny>) -> PyResult { if let Ok(component_str) = component.extract::() { - Ok(Self(component_str.into())) + Ok(Self(component_str)) } else if let Ok(component_str) = component .getattr("_BATCH_TYPE") .and_then(|batch_type| batch_type.getattr("_ARROW_TYPE")) .and_then(|arrow_type| arrow_type.getattr("_TYPE_NAME")) .and_then(|type_name| type_name.extract::()) { - Ok(Self(component_str.into())) + Ok(Self(component_str)) } else { return Err(PyTypeError::new_err( "ComponentLike input must be a string or Component class.", @@ -597,6 +596,18 @@ impl PyRecording { } } + fn find_best_component(&self, entity_path: &EntityPath, component_name: &str) -> ComponentName { + let selector = ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: component_name.into(), + join_encoding: Default::default(), + }; + + self.store + .resolve_component_selector(&selector) + .component_name + } + /// Convert a `ViewContentsLike` into a `ViewContentsSelector`. /// /// ```pytholn @@ -631,6 +642,7 @@ impl PyRecording { // `Union[ComponentLike, Sequence[ComponentLike]]]` let mut contents = ViewContentsSelector::default(); + for (key, value) in dict { let key = key.extract::().map_err(|_err| { PyTypeError::new_err( @@ -644,7 +656,7 @@ impl PyRecording { )) })?; - let components: BTreeSet = if let Ok(component) = + let component_strs: BTreeSet = if let Ok(component) = value.extract::() { std::iter::once(component.0).collect() @@ -659,7 +671,15 @@ impl PyRecording { contents.append( &mut engine .iter_entity_paths(&path_filter) - .map(|p| (p, Some(components.clone()))) + .map(|entity_path| { + let components = component_strs + .iter() + .map(|component_name| { + self.find_best_component(&entity_path, component_name) + }) + .collect(); + (entity_path, Some(components)) + }) .collect(), ); } diff --git a/rerun_py/tests/unit/test_dataframe.py b/rerun_py/tests/unit/test_dataframe.py index 5532ca283fbc..072542d239c9 100644 --- a/rerun_py/tests/unit/test_dataframe.py +++ b/rerun_py/tests/unit/test_dataframe.py @@ -108,19 +108,22 @@ def test_full_view(self) -> None: def test_select_columns(self) -> None: view = self.recording.view(index="my_index", contents="points") index_col = rr.dataframe.IndexColumnSelector("my_index") - pos = rr.dataframe.ComponentColumnSelector("points", rr.components.Position3D) - batches = view.select(index_col, pos) + selectors = [rr.components.Position3D, "rerun.components.Position3D", "Position3D", "position3D"] + for selector in selectors: + pos = rr.dataframe.ComponentColumnSelector("points", selector) - table = pa.Table.from_batches(batches, batches.schema) - # points - assert table.num_columns == 2 - assert table.num_rows == 2 + batches = view.select(index_col, pos) - assert table.column("my_index")[0].equals(self.expected_index0[0]) - assert table.column("my_index")[1].equals(self.expected_index1[0]) - assert table.column("/points:Position3D")[0].values.equals(self.expected_pos0) - assert table.column("/points:Position3D")[1].values.equals(self.expected_pos1) + table = pa.Table.from_batches(batches, batches.schema) + # points + assert table.num_columns == 2 + assert table.num_rows == 2 + + assert table.column("my_index")[0].equals(self.expected_index0[0]) + assert table.column("my_index")[1].equals(self.expected_index1[0]) + assert table.column("/points:Position3D")[0].values.equals(self.expected_pos0) + assert table.column("/points:Position3D")[1].values.equals(self.expected_pos1) def test_index_values(self) -> None: view = self.recording.view(index="my_index", contents="points") @@ -248,6 +251,8 @@ def test_view_syntax(self) -> None: {"points": [rr.components.Position3D]}, {"points": "rerun.components.Position3D"}, {"points/**": "rerun.components.Position3D"}, + {"points/**": "Position3D"}, + {"points/**": "position3D"}, ] for expr in good_content_expressions: From b32e69cd382258f7a1da5cbcf6b72277abd11007 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 11 Oct 2024 23:17:53 +0200 Subject: [PATCH 16/33] Dataframe v2: new static semantics (#7696) --- crates/store/re_chunk_store/src/dataframe.rs | 45 +- crates/store/re_dataframe/examples/query.rs | 21 +- crates/store/re_dataframe/src/query.rs | 793 +++++++++++------- .../src/dataframe_ui.rs | 33 +- .../src/space_view_class.rs | 2 +- rerun_py/src/dataframe.rs | 62 +- 6 files changed, 573 insertions(+), 383 deletions(-) diff --git a/crates/store/re_chunk_store/src/dataframe.rs b/crates/store/re_chunk_store/src/dataframe.rs index 42c6a33e0082..3916deb4a76d 100644 --- a/crates/store/re_chunk_store/src/dataframe.rs +++ b/crates/store/re_chunk_store/src/dataframe.rs @@ -575,8 +575,7 @@ pub type IndexRange = ResolvedTimeRange; /// ``` // // TODO(cmc): ideally we'd like this to be the same type as the one used in the blueprint, possibly? -// TODO(cmc): Get rid of all re_dataframe (as opposed to re_dataframe) stuff and rename this. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)] pub struct QueryExpression { /// The subset of the database that the query will run on: a set of [`EntityPath`]s and their /// associated [`ComponentName`]s. @@ -619,17 +618,20 @@ pub struct QueryExpression { /// Only rows where at least 1 column contains non-null data at that index will be kept in the /// final dataset. /// - /// Example: `Timeline("frame")`. + /// If left unspecified, the results will only contain static data. + /// + /// Examples: `Some(Timeline("frame"))`, `None` (only static data). // // TODO(cmc): this has to be a selector otherwise this is a horrible UX. - pub filtered_index: Timeline, + pub filtered_index: Option, /// The range of index values used to filter out _rows_ from the view contents. /// /// Only rows where at least 1 of the view-contents contains non-null data within that range will be kept in /// the final dataset. /// - /// This is ignored if [`QueryExpression::using_index_values`] is set. + /// * This has no effect if `filtered_index` isn't set. + /// * This has no effect if [`QueryExpression::using_index_values`] is set. /// /// Example: `ResolvedTimeRange(10, 20)`. pub filtered_index_range: Option, @@ -639,7 +641,9 @@ pub struct QueryExpression { /// Only rows where at least 1 column contains non-null data at these specific values will be kept /// in the final dataset. /// - /// This is ignored if [`QueryExpression::using_index_values`] is set. + /// * This has no effect if `filtered_index` isn't set. + /// * This has no effect if [`QueryExpression::using_index_values`] is set. + /// * Using [`TimeInt::STATIC`] as index value has no effect. /// /// Example: `[TimeInt(12), TimeInt(14)]`. pub filtered_index_values: Option>, @@ -651,10 +655,10 @@ pub struct QueryExpression { /// The semantics of the query are consistent with all other settings: the results will be /// sorted on the `filtered_index`, and only contain unique index values. /// - /// The order of the samples will be respected in the final result. - /// - /// If [`QueryExpression::using_index_values`] is set, it overrides both [`QueryExpression::filtered_index_range`] - /// and [`QueryExpression::filtered_index_values`]. + /// * This has no effect if `filtered_index` isn't set. + /// * If set, this overrides both [`QueryExpression::filtered_index_range`] and + /// [`QueryExpression::filtered_index_values`]. + /// * Using [`TimeInt::STATIC`] as index value has no effect. /// /// Example: `[TimeInt(12), TimeInt(14)]`. pub using_index_values: Option>, @@ -685,27 +689,6 @@ pub struct QueryExpression { pub selection: Option>, } -impl QueryExpression { - #[inline] - pub fn new(index: impl Into) -> Self { - let index = index.into(); - - Self { - view_contents: None, - include_semantically_empty_columns: false, - include_indicator_columns: false, - include_tombstone_columns: false, - filtered_index: index, - filtered_index_range: None, - filtered_index_values: None, - using_index_values: None, - filtered_point_of_view: None, - sparse_fill_strategy: SparseFillStrategy::None, - selection: None, - } - } -} - // --- impl ChunkStore { diff --git a/crates/store/re_dataframe/examples/query.rs b/crates/store/re_dataframe/examples/query.rs index 64d2f302455c..7d374587d45b 100644 --- a/crates/store/re_dataframe/examples/query.rs +++ b/crates/store/re_dataframe/examples/query.rs @@ -59,15 +59,18 @@ fn main() -> anyhow::Result<()> { cache: &query_cache, }; - let mut query = QueryExpression::new(timeline); - query.view_contents = Some( - query_engine - .iter_entity_paths(&entity_path_filter) - .map(|entity_path| (entity_path, None)) - .collect(), - ); - query.filtered_index_range = Some(ResolvedTimeRange::new(time_from, time_to)); - query.sparse_fill_strategy = SparseFillStrategy::LatestAtGlobal; + let query = QueryExpression { + filtered_index: Some(timeline), + view_contents: Some( + query_engine + .iter_entity_paths(&entity_path_filter) + .map(|entity_path| (entity_path, None)) + .collect(), + ), + filtered_index_range: Some(ResolvedTimeRange::new(time_from, time_to)), + sparse_fill_strategy: SparseFillStrategy::LatestAtGlobal, + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); diff --git a/crates/store/re_dataframe/src/query.rs b/crates/store/re_dataframe/src/query.rs index 96dc02798b79..529a16078694 100644 --- a/crates/store/re_dataframe/src/query.rs +++ b/crates/store/re_dataframe/src/query.rs @@ -22,7 +22,7 @@ use re_chunk::{ Chunk, ComponentName, EntityPath, RangeQuery, RowId, TimeInt, Timeline, UnitChunkShared, }; use re_chunk_store::{ - ColumnDescriptor, ColumnSelector, ComponentColumnDescriptor, ComponentColumnSelector, + ColumnDescriptor, ColumnSelector, ComponentColumnDescriptor, ComponentColumnSelector, Index, IndexValue, JoinEncoding, QueryExpression, SparseFillStrategy, TimeColumnDescriptor, TimeColumnSelector, }; @@ -87,6 +87,19 @@ struct QueryHandleState { /// See also [`QueryHandleState::arrow_schema`]. selected_contents: Vec<(usize, ColumnDescriptor)>, + /// This keeps track of the static data associated with each entry in `selected_contents`, if any. + /// + /// This is queried only once during init, and will override all cells that follow. + /// + /// `selected_contents`: [`QueryHandleState::selected_contents`] + selected_static_values: Vec>, + + /// The actual index filter in use, since the user-specified one is optional. + /// + /// This just defaults to `Index::default()` if the user hasn't specified any: the actual + /// value is irrelevant since this means we are only concerned with static data anyway. + filtered_index: Index, + /// The Arrow schema that corresponds to the `selected_contents`. /// /// All returned rows will have this schema. @@ -150,6 +163,9 @@ impl QueryHandle<'_> { fn init_(&self) -> QueryHandleState { re_tracing::profile_scope!("init"); + // The timeline doesn't matter if we're running in static-only mode. + let filtered_index = self.query.filtered_index.unwrap_or_default(); + // 1. Compute the schema for the query. let view_contents = self.engine.store.schema_for_query(&self.query); @@ -177,21 +193,22 @@ impl QueryHandle<'_> { // 4. Perform the query and keep track of all the relevant chunks. let query = { - let index_range = - if let Some(using_index_values) = self.query.using_index_values.as_ref() { - using_index_values - .first() - .and_then(|start| using_index_values.last().map(|end| (start, end))) - .map_or(ResolvedTimeRange::EMPTY, |(start, end)| { - ResolvedTimeRange::new(*start, *end) - }) - } else { - self.query - .filtered_index_range - .unwrap_or(ResolvedTimeRange::EVERYTHING) - }; + let index_range = if self.query.filtered_index.is_none() { + ResolvedTimeRange::EMPTY // static-only + } else if let Some(using_index_values) = self.query.using_index_values.as_ref() { + using_index_values + .first() + .and_then(|start| using_index_values.last().map(|end| (start, end))) + .map_or(ResolvedTimeRange::EMPTY, |(start, end)| { + ResolvedTimeRange::new(*start, *end) + }) + } else { + self.query + .filtered_index_range + .unwrap_or(ResolvedTimeRange::EVERYTHING) + }; - RangeQuery::new(self.query.filtered_index, index_range) + RangeQuery::new(filtered_index, index_range) .keep_extra_timelines(true) // we want all the timelines we can get! .keep_extra_components(false) }; @@ -248,7 +265,7 @@ impl QueryHandle<'_> { // the time range for the specific component of interest. chunk .timelines() - .get(&self.query.filtered_index) + .get(&filtered_index) .map(|time_column| time_column.time_range()) .map_or(TimeInt::STATIC, |time_range| time_range.min()) }); @@ -259,45 +276,75 @@ impl QueryHandle<'_> { // 6. Collect all unique index values. // // Used to achieve ~O(log(n)) pagination. - let unique_index_values = - if let Some(using_index_values) = self.query.using_index_values.as_ref() { - using_index_values.iter().copied().collect_vec() - } else { - re_tracing::profile_scope!("index_values"); + let unique_index_values = if self.query.filtered_index.is_none() { + vec![TimeInt::STATIC] + } else if let Some(using_index_values) = self.query.using_index_values.as_ref() { + using_index_values + .iter() + .filter(|index_value| !index_value.is_static()) + .copied() + .collect_vec() + } else { + re_tracing::profile_scope!("index_values"); - let mut view_chunks = view_chunks.iter(); - let view_chunks = if let Some(view_pov_chunks_idx) = view_pov_chunks_idx { - Either::Left(view_chunks.nth(view_pov_chunks_idx).into_iter()) - } else { - Either::Right(view_chunks) - }; + let mut view_chunks = view_chunks.iter(); + let view_chunks = if let Some(view_pov_chunks_idx) = view_pov_chunks_idx { + Either::Left(view_chunks.nth(view_pov_chunks_idx).into_iter()) + } else { + Either::Right(view_chunks) + }; - let mut all_unique_index_values: BTreeSet = view_chunks - .flat_map(|chunks| { - chunks.iter().filter_map(|(_cursor, chunk)| { - if chunk.is_static() { - Some(Either::Left(std::iter::once(TimeInt::STATIC))) - } else { - chunk - .timelines() - .get(&self.query.filtered_index) - .map(|time_column| Either::Right(time_column.times())) - } - }) + let mut all_unique_index_values: BTreeSet = view_chunks + .flat_map(|chunks| { + chunks.iter().filter_map(|(_cursor, chunk)| { + chunk + .timelines() + .get(&filtered_index) + .map(|time_column| time_column.times()) }) - .flatten() - .collect(); + }) + .flatten() + .collect(); - if let Some(filtered_index_values) = self.query.filtered_index_values.as_ref() { - all_unique_index_values.retain(|time| filtered_index_values.contains(time)); - } + if let Some(filtered_index_values) = self.query.filtered_index_values.as_ref() { + all_unique_index_values.retain(|time| filtered_index_values.contains(time)); + } - all_unique_index_values.into_iter().collect_vec() - }; + all_unique_index_values + .into_iter() + .filter(|index_value| !index_value.is_static()) + .collect_vec() + }; + + let selected_static_values = { + re_tracing::profile_scope!("static_values"); + + selected_contents + .iter() + .map(|(_view_idx, descr)| match descr { + ColumnDescriptor::Time(_) => None, + ColumnDescriptor::Component(descr) => { + let query = + re_chunk::LatestAtQuery::new(Timeline::default(), TimeInt::STATIC); + + let results = self.engine.cache.latest_at( + self.engine.store, + &query, + &descr.entity_path, + [descr.component_name], + ); + + results.components.get(&descr.component_name).cloned() + } + }) + .collect_vec() + }; QueryHandleState { view_contents, selected_contents, + selected_static_values, + filtered_index, arrow_schema, view_chunks, cur_row: AtomicU64::new(0), @@ -576,7 +623,7 @@ impl QueryHandle<'_> { "the query cache should have already taken care of sorting (and densifying!) the chunk", ); - let chunk = chunk.deduped_latest_on_index(&self.query.filtered_index); + let chunk = chunk.deduped_latest_on_index(&query.timeline); (AtomicU64::default(), chunk) }) @@ -679,7 +726,7 @@ impl QueryHandle<'_> { for (cursor, chunk) in chunks { // NOTE: The chunk has been densified already: its global time range is the same as // the time range for the specific component of interest. - let Some(time_column) = chunk.timelines().get(&self.query.filtered_index) else { + let Some(time_column) = chunk.timelines().get(&state.filtered_index) else { continue; }; @@ -802,9 +849,7 @@ impl QueryHandle<'_> { // TODO(cmc): make this a tiny bit smarter so we can remove the need for // deduped_latest_on_index, which would be very welcome right now given we don't // have an Arrow ListView at our disposal. - let cur_indices = cur_chunk - .iter_indices(&self.query.filtered_index) - .collect_vec(); + let cur_indices = cur_chunk.iter_indices(&state.filtered_index).collect_vec(); let (index_value, cur_row_id) = 'walk: loop { let Some((index_value, cur_row_id)) = cur_indices.get(cur_cursor_value as usize).copied() @@ -852,8 +897,22 @@ impl QueryHandle<'_> { .map(|streaming_state| streaming_state.map(StreamingJoinState::StreamingJoinState)) .collect_vec(); + // Static always wins, no matter what. + for (view_idx, streaming_state) in view_streaming_state.iter_mut().enumerate() { + if let static_state @ Some(_) = state + .selected_static_values + .get(view_idx) + .cloned() + .flatten() + .map(StreamingJoinState::Retrofilled) + { + *streaming_state = static_state; + } + } + match self.query.sparse_fill_strategy { SparseFillStrategy::None => {} + SparseFillStrategy::LatestAtGlobal => { // Everything that yielded `null` for the current iteration. let null_streaming_states = view_streaming_state @@ -881,7 +940,7 @@ impl QueryHandle<'_> { // consecutive nulls etc). Later. let query = - re_chunk::LatestAtQuery::new(self.query.filtered_index, *cur_index_value); + re_chunk::LatestAtQuery::new(state.filtered_index, *cur_index_value); let results = self.engine.cache.latest_at( self.engine.store, @@ -961,11 +1020,11 @@ impl QueryHandle<'_> { // The current index value (if temporal) should be the one returned for the // queried index, no matter what. max_value_per_index.insert( - self.query.filtered_index, + state.filtered_index, ( *cur_index_value, ArrowPrimitiveArray::::from_vec(vec![cur_index_value.as_i64()]) - .to(self.query.filtered_index.datatype()) + .to(state.filtered_index.datatype()) .to_boxed(), ), ); @@ -1146,35 +1205,74 @@ mod tests { cache: &query_cache, }; - let timeline = Timeline::new_sequence("frame_nr"); - let query = QueryExpression::new(timeline); - eprintln!("{query:#?}:"); + let filtered_index = Some(Timeline::new_sequence("frame_nr")); - let query_handle = query_engine.query(query.clone()); - assert_eq!( - query_engine.query(query.clone()).into_iter().count() as u64, - query_handle.num_rows() - ); - let dataframe = concatenate_record_batches( - query_handle.schema().clone(), - &query_handle.into_batch_iter().collect_vec(), - ); - eprintln!("{dataframe}"); + // static + { + let query = QueryExpression::default(); + eprintln!("{query:#?}:"); - let got = format!("{:#?}", dataframe.data.iter().collect_vec()); - let expected = unindent::unindent( - "\ - [ - Int64[None, 10, 20, 30, 40, 50, 60, 70], - Timestamp(Nanosecond, None)[None, 1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, None, 1970-01-01 00:00:00.000000070], - ListArray[None, None, None, [2], [3], [4], None, [6]], - ListArray[[c], None, None, None, None, None, None, None], - ListArray[None, [{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 5, y: 5}], [{x: 8, y: 8}]], - ]\ - " - ); + let query_handle = query_engine.query(query.clone()); + assert_eq!( + query_engine.query(query.clone()).into_iter().count() as u64, + query_handle.num_rows() + ); + let dataframe = concatenate_record_batches( + query_handle.schema().clone(), + &query_handle.into_batch_iter().collect_vec(), + ); + eprintln!("{dataframe}"); - similar_asserts::assert_eq!(expected, got); + let got = format!("{:#?}", dataframe.data.iter().collect_vec()); + let expected = unindent::unindent( + "\ + [ + Int64[None], + Timestamp(Nanosecond, None)[None], + ListArray[None], + ListArray[[c]], + ListArray[None], + ]\ + ", + ); + + similar_asserts::assert_eq!(expected, got); + } + + // temporal + { + let query = QueryExpression { + filtered_index, + ..Default::default() + }; + eprintln!("{query:#?}:"); + + let query_handle = query_engine.query(query.clone()); + assert_eq!( + query_engine.query(query.clone()).into_iter().count() as u64, + query_handle.num_rows() + ); + let dataframe = concatenate_record_batches( + query_handle.schema().clone(), + &query_handle.into_batch_iter().collect_vec(), + ); + eprintln!("{dataframe}"); + + let got = format!("{:#?}", dataframe.data.iter().collect_vec()); + let expected = unindent::unindent( + "\ + [ + Int64[10, 20, 30, 40, 50, 60, 70], + Timestamp(Nanosecond, None)[1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, None, 1970-01-01 00:00:00.000000070], + ListArray[None, None, [2], [3], [4], None, [6]], + ListArray[[c], [c], [c], [c], [c], [c], [c]], + ListArray[[{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 5, y: 5}], [{x: 8, y: 8}]], + ]\ + " + ); + + similar_asserts::assert_eq!(expected, got); + } Ok(()) } @@ -1191,9 +1289,12 @@ mod tests { cache: &query_cache, }; - let timeline = Timeline::new_sequence("frame_nr"); - let mut query = QueryExpression::new(timeline); - query.sparse_fill_strategy = SparseFillStrategy::LatestAtGlobal; + let filtered_index = Some(Timeline::new_sequence("frame_nr")); + let query = QueryExpression { + filtered_index, + sparse_fill_strategy: SparseFillStrategy::LatestAtGlobal, + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1211,11 +1312,11 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 10, 20, 30, 40, 50, 60, 70], - Timestamp(Nanosecond, None)[None, 1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, None, 1970-01-01 00:00:00.000000070], - ListArray[None, None, None, [2], [3], [4], [4], [6]], - ListArray[[c], [c], [c], [c], [c], [c], [c], [c]], - ListArray[None, [{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 5, y: 5}], [{x: 8, y: 8}]], + Int64[10, 20, 30, 40, 50, 60, 70], + Timestamp(Nanosecond, None)[1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, None, 1970-01-01 00:00:00.000000070], + ListArray[None, None, [2], [3], [4], [4], [6]], + ListArray[[c], [c], [c], [c], [c], [c], [c]], + ListArray[[{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 5, y: 5}], [{x: 8, y: 8}]], ]\ " ); @@ -1237,9 +1338,12 @@ mod tests { cache: &query_cache, }; - let timeline = Timeline::new_sequence("frame_nr"); - let mut query = QueryExpression::new(timeline); - query.filtered_index_range = Some(ResolvedTimeRange::new(30, 60)); + let filtered_index = Some(Timeline::new_sequence("frame_nr")); + let query = QueryExpression { + filtered_index, + filtered_index_range: Some(ResolvedTimeRange::new(30, 60)), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1257,11 +1361,11 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 30, 40, 50, 60], - Timestamp(Nanosecond, None)[None, None, None, 1970-01-01 00:00:00.000000050, None], - ListArray[None, [2], [3], [4], None], - ListArray[[c], None, None, None, None], - ListArray[None, [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 5, y: 5}]], + Int64[30, 40, 50, 60], + Timestamp(Nanosecond, None)[None, None, 1970-01-01 00:00:00.000000050, None], + ListArray[[2], [3], [4], None], + ListArray[[c], [c], [c], [c]], + ListArray[[{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 5, y: 5}]], ]\ ", ); @@ -1283,15 +1387,18 @@ mod tests { cache: &query_cache, }; - let timeline = Timeline::new_sequence("frame_nr"); - let mut query = QueryExpression::new(timeline); - query.filtered_index_values = Some( - [0, 30, 60, 90] - .into_iter() - .map(TimeInt::new_temporal) - .chain(std::iter::once(TimeInt::STATIC)) - .collect(), - ); + let filtered_index = Some(Timeline::new_sequence("frame_nr")); + let query = QueryExpression { + filtered_index, + filtered_index_values: Some( + [0, 30, 60, 90] + .into_iter() + .map(TimeInt::new_temporal) + .chain(std::iter::once(TimeInt::STATIC)) + .collect(), + ), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1309,11 +1416,11 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 30, 60], - Timestamp(Nanosecond, None)[None, None, None], - ListArray[None, [2], None], - ListArray[[c], None, None], - ListArray[None, [{x: 2, y: 2}], [{x: 5, y: 5}]], + Int64[30, 60], + Timestamp(Nanosecond, None)[None, None], + ListArray[[2], None], + ListArray[[c], [c]], + ListArray[[{x: 2, y: 2}], [{x: 5, y: 5}]], ]\ ", ); @@ -1335,18 +1442,21 @@ mod tests { cache: &query_cache, }; - let timeline = Timeline::new_sequence("frame_nr"); + let filtered_index = Some(Timeline::new_sequence("frame_nr")); // vanilla { - let mut query = QueryExpression::new(timeline); - query.using_index_values = Some( - [0, 15, 30, 30, 45, 60, 75, 90] - .into_iter() - .map(TimeInt::new_temporal) - .chain(std::iter::once(TimeInt::STATIC)) - .collect(), - ); + let query = QueryExpression { + filtered_index, + using_index_values: Some( + [0, 15, 30, 30, 45, 60, 75, 90] + .into_iter() + .map(TimeInt::new_temporal) + .chain(std::iter::once(TimeInt::STATIC)) + .collect(), + ), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1364,11 +1474,11 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 0, 15, 30, 45, 60, 75, 90], - Timestamp(Nanosecond, None)[None, None, None, None, None, None, None, None], - ListArray[None, None, None, [2], None, None, None, None], - ListArray[[c], None, None, None, None, None, None, None], - ListArray[None, None, None, [{x: 2, y: 2}], None, [{x: 5, y: 5}], None, None], + Int64[0, 15, 30, 45, 60, 75, 90], + Timestamp(Nanosecond, None)[None, None, None, None, None, None, None], + ListArray[None, None, [2], None, None, None, None], + ListArray[[c], [c], [c], [c], [c], [c], [c]], + ListArray[None, None, [{x: 2, y: 2}], None, [{x: 5, y: 5}], None, None], ]\ ", ); @@ -1377,16 +1487,19 @@ mod tests { } // sparse-filled - if true { - let mut query = QueryExpression::new(timeline); - query.using_index_values = Some( - [0, 15, 30, 30, 45, 60, 75, 90] - .into_iter() - .map(TimeInt::new_temporal) - .chain(std::iter::once(TimeInt::STATIC)) - .collect(), - ); - query.sparse_fill_strategy = SparseFillStrategy::LatestAtGlobal; + { + let query = QueryExpression { + filtered_index, + using_index_values: Some( + [0, 15, 30, 30, 45, 60, 75, 90] + .into_iter() + .map(TimeInt::new_temporal) + .chain(std::iter::once(TimeInt::STATIC)) + .collect(), + ), + sparse_fill_strategy: SparseFillStrategy::LatestAtGlobal, + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1404,11 +1517,11 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 0, 15, 30, 45, 60, 75, 90], - Timestamp(Nanosecond, None)[None, None, 1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000070, 1970-01-01 00:00:00.000000070], - ListArray[None, None, None, [2], [3], [4], [6], [6]], - ListArray[[c], [c], [c], [c], [c], [c], [c], [c]], - ListArray[None, None, [{x: 0, y: 0}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 5, y: 5}], [{x: 8, y: 8}], [{x: 8, y: 8}]], + Int64[0, 15, 30, 45, 60, 75, 90], + Timestamp(Nanosecond, None)[None, 1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000070, 1970-01-01 00:00:00.000000070], + ListArray[None, None, [2], [3], [4], [6], [6]], + ListArray[[c], [c], [c], [c], [c], [c], [c]], + ListArray[None, [{x: 0, y: 0}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 5, y: 5}], [{x: 8, y: 8}], [{x: 8, y: 8}]], ]\ ", ); @@ -1431,17 +1544,20 @@ mod tests { cache: &query_cache, }; - let timeline = Timeline::new_sequence("frame_nr"); + let filtered_index = Some(Timeline::new_sequence("frame_nr")); let entity_path: EntityPath = "this/that".into(); // non-existing entity { - let mut query = QueryExpression::new(timeline); - query.filtered_point_of_view = Some(ComponentColumnSelector { - entity_path: "no/such/entity".into(), - component_name: MyPoint::name().to_string(), - join_encoding: Default::default(), - }); + let query = QueryExpression { + filtered_index, + filtered_point_of_view: Some(ComponentColumnSelector { + entity_path: "no/such/entity".into(), + component_name: MyPoint::name().to_string(), + join_encoding: Default::default(), + }), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1463,12 +1579,15 @@ mod tests { // non-existing component { - let mut query = QueryExpression::new(timeline); - query.filtered_point_of_view = Some(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: "AComponentColumnThatDoesntExist".into(), - join_encoding: Default::default(), - }); + let query = QueryExpression { + filtered_index, + filtered_point_of_view: Some(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: "AComponentColumnThatDoesntExist".into(), + join_encoding: Default::default(), + }), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1490,12 +1609,15 @@ mod tests { // MyPoint { - let mut query = QueryExpression::new(timeline); - query.filtered_point_of_view = Some(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: MyPoint::name().to_string(), - join_encoding: Default::default(), - }); + let query = QueryExpression { + filtered_index, + filtered_point_of_view: Some(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: MyPoint::name().to_string(), + join_encoding: Default::default(), + }), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1516,7 +1638,7 @@ mod tests { Int64[10, 20, 30, 40, 50, 60, 70], Timestamp(Nanosecond, None)[1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, None, 1970-01-01 00:00:00.000000070], ListArray[None, None, [2], [3], [4], None, [6]], - ListArray[None, None, None, None, None, None, None], + ListArray[[c], [c], [c], [c], [c], [c], [c]], ListArray[[{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 5, y: 5}], [{x: 8, y: 8}]], ]\ " @@ -1527,12 +1649,15 @@ mod tests { // MyColor { - let mut query = QueryExpression::new(timeline); - query.filtered_point_of_view = Some(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: MyColor::name().to_string(), - join_encoding: Default::default(), - }); + let query = QueryExpression { + filtered_index, + filtered_point_of_view: Some(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: MyColor::name().to_string(), + join_encoding: Default::default(), + }), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1553,7 +1678,7 @@ mod tests { Int64[30, 40, 50, 70], Timestamp(Nanosecond, None)[None, None, 1970-01-01 00:00:00.000000050, 1970-01-01 00:00:00.000000070], ListArray[[2], [3], [4], [6]], - ListArray[None, None, None, None], + ListArray[[c], [c], [c], [c]], ListArray[[{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [{x: 8, y: 8}]], ]\ ", @@ -1578,16 +1703,19 @@ mod tests { }; let entity_path: EntityPath = "this/that".into(); - let timeline = Timeline::new_sequence("frame_nr"); + let filtered_index = Some(Timeline::new_sequence("frame_nr")); // empty view { - let mut query = QueryExpression::new(timeline); - query.view_contents = Some( - [(entity_path.clone(), Some(Default::default()))] - .into_iter() - .collect(), - ); + let query = QueryExpression { + filtered_index, + view_contents: Some( + [(entity_path.clone(), Some(Default::default()))] + .into_iter() + .collect(), + ), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1608,23 +1736,26 @@ mod tests { } { - let mut query = QueryExpression::new(timeline); - query.view_contents = Some( - [( - entity_path.clone(), - Some( - [ - MyLabel::name(), - MyColor::name(), - "AColumnThatDoesntEvenExist".into(), - ] - .into_iter() - .collect(), - ), - )] - .into_iter() - .collect(), - ); + let query = QueryExpression { + filtered_index, + view_contents: Some( + [( + entity_path.clone(), + Some( + [ + MyLabel::name(), + MyColor::name(), + "AColumnThatDoesntEvenExist".into(), + ] + .into_iter() + .collect(), + ), + )] + .into_iter() + .collect(), + ), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1642,10 +1773,10 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 30, 40, 50, 70], - Timestamp(Nanosecond, None)[None, None, None, None, None], - ListArray[None, [2], [3], [4], [6]], - ListArray[[c], None, None, None, None], + Int64[30, 40, 50, 70], + Timestamp(Nanosecond, None)[None, None, None, None], + ListArray[[2], [3], [4], [6]], + ListArray[[c], [c], [c], [c]], ]\ ", ); @@ -1669,12 +1800,15 @@ mod tests { }; let entity_path: EntityPath = "this/that".into(); - let timeline = Timeline::new_sequence("frame_nr"); + let filtered_index = Timeline::new_sequence("frame_nr"); // empty selection { - let mut query = QueryExpression::new(timeline); - query.selection = Some(vec![]); + let query = QueryExpression { + filtered_index: Some(filtered_index), + selection: Some(vec![]), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1696,18 +1830,21 @@ mod tests { // only indices (+ duplication) { - let mut query = QueryExpression::new(timeline); - query.selection = Some(vec![ - ColumnSelector::Time(TimeColumnSelector { - timeline: *timeline.name(), - }), - ColumnSelector::Time(TimeColumnSelector { - timeline: *timeline.name(), - }), - ColumnSelector::Time(TimeColumnSelector { - timeline: "ATimeColumnThatDoesntExist".into(), - }), - ]); + let query = QueryExpression { + filtered_index: Some(filtered_index), + selection: Some(vec![ + ColumnSelector::Time(TimeColumnSelector { + timeline: *filtered_index.name(), + }), + ColumnSelector::Time(TimeColumnSelector { + timeline: *filtered_index.name(), + }), + ColumnSelector::Time(TimeColumnSelector { + timeline: "ATimeColumnThatDoesntExist".into(), + }), + ]), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1725,9 +1862,9 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 10, 20, 30, 40, 50, 60, 70], - Int64[None, 10, 20, 30, 40, 50, 60, 70], - NullArray(8), + Int64[10, 20, 30, 40, 50, 60, 70], + Int64[10, 20, 30, 40, 50, 60, 70], + NullArray(7), ]\ ", ); @@ -1737,29 +1874,32 @@ mod tests { // only components (+ duplication) { - let mut query = QueryExpression::new(timeline); - query.selection = Some(vec![ - ColumnSelector::Component(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: MyColor::name().to_string(), - join_encoding: Default::default(), - }), - ColumnSelector::Component(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: MyColor::name().to_string(), - join_encoding: Default::default(), - }), - ColumnSelector::Component(ComponentColumnSelector { - entity_path: "non_existing_entity".into(), - component_name: MyColor::name().to_string(), - join_encoding: Default::default(), - }), - ColumnSelector::Component(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: "AComponentColumnThatDoesntExist".into(), - join_encoding: Default::default(), - }), - ]); + let query = QueryExpression { + filtered_index: Some(filtered_index), + selection: Some(vec![ + ColumnSelector::Component(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: MyColor::name().to_string(), + join_encoding: Default::default(), + }), + ColumnSelector::Component(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: MyColor::name().to_string(), + join_encoding: Default::default(), + }), + ColumnSelector::Component(ComponentColumnSelector { + entity_path: "non_existing_entity".into(), + component_name: MyColor::name().to_string(), + join_encoding: Default::default(), + }), + ColumnSelector::Component(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: "AComponentColumnThatDoesntExist".into(), + join_encoding: Default::default(), + }), + ]), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1777,10 +1917,10 @@ mod tests { let expected = unindent::unindent( "\ [ - ListArray[None, None, None, [2], [3], [4], None, [6]], - ListArray[None, None, None, [2], [3], [4], None, [6]], - NullArray(8), - NullArray(8), + ListArray[None, None, [2], [3], [4], None, [6]], + ListArray[None, None, [2], [3], [4], None, [6]], + NullArray(7), + NullArray(7), ]\ ", ); @@ -1804,46 +1944,49 @@ mod tests { }; let entity_path: EntityPath = "this/that".into(); - let timeline = Timeline::new_sequence("frame_nr"); + let filtered_index = Timeline::new_sequence("frame_nr"); // only components { - let mut query = QueryExpression::new(timeline); - query.view_contents = Some( - [( - entity_path.clone(), - Some([MyColor::name(), MyLabel::name()].into_iter().collect()), - )] - .into_iter() - .collect(), - ); - query.selection = Some(vec![ - ColumnSelector::Time(TimeColumnSelector { - timeline: *timeline.name(), - }), - ColumnSelector::Time(TimeColumnSelector { - timeline: *Timeline::log_time().name(), - }), - ColumnSelector::Time(TimeColumnSelector { - timeline: *Timeline::log_tick().name(), - }), - // - ColumnSelector::Component(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: MyPoint::name().to_string(), - join_encoding: Default::default(), - }), - ColumnSelector::Component(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: MyColor::name().to_string(), - join_encoding: Default::default(), - }), - ColumnSelector::Component(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: MyLabel::name().to_string(), - join_encoding: Default::default(), - }), - ]); + let query = QueryExpression { + filtered_index: Some(filtered_index), + view_contents: Some( + [( + entity_path.clone(), + Some([MyColor::name(), MyLabel::name()].into_iter().collect()), + )] + .into_iter() + .collect(), + ), + selection: Some(vec![ + ColumnSelector::Time(TimeColumnSelector { + timeline: *filtered_index.name(), + }), + ColumnSelector::Time(TimeColumnSelector { + timeline: *Timeline::log_time().name(), + }), + ColumnSelector::Time(TimeColumnSelector { + timeline: *Timeline::log_tick().name(), + }), + // + ColumnSelector::Component(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: MyPoint::name().to_string(), + join_encoding: Default::default(), + }), + ColumnSelector::Component(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: MyColor::name().to_string(), + join_encoding: Default::default(), + }), + ColumnSelector::Component(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: MyLabel::name().to_string(), + join_encoding: Default::default(), + }), + ]), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1861,12 +2004,12 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 30, 40, 50, 70], - Timestamp(Nanosecond, None)[None, None, None, None, None], - NullArray(5), - NullArray(5), - ListArray[None, [2], [3], [4], [6]], - ListArray[[c], None, None, None, None], + Int64[30, 40, 50, 70], + Timestamp(Nanosecond, None)[None, None, None, None], + NullArray(4), + NullArray(4), + ListArray[[2], [3], [4], [6]], + ListArray[None, None, None, None], ]\ ", ); @@ -1891,13 +2034,16 @@ mod tests { cache: &query_cache, }; - let timeline = Timeline::new_sequence("frame_nr"); + let filtered_index = Some(Timeline::new_sequence("frame_nr")); let entity_path = EntityPath::from("this/that"); // barebones { - let mut query = QueryExpression::new(timeline); - query.view_contents = Some([(entity_path.clone(), None)].into_iter().collect()); + let query = QueryExpression { + filtered_index, + view_contents: Some([(entity_path.clone(), None)].into_iter().collect()), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1915,11 +2061,11 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 10, 20, 30, 40, 50, 60, 65, 70], - Timestamp(Nanosecond, None)[None, 1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, 1970-01-01 00:00:00.000000060, 1970-01-01 00:00:00.000000065, 1970-01-01 00:00:00.000000070], - ListArray[[], None, None, [2], [3], [4], [], [], [6]], - ListArray[[], None, None, None, None, None, [], [], None], - ListArray[[], [{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [], [], [{x: 8, y: 8}]], + Int64[10, 20, 30, 40, 50, 60, 65, 70], + Timestamp(Nanosecond, None)[1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, 1970-01-01 00:00:00.000000060, 1970-01-01 00:00:00.000000065, 1970-01-01 00:00:00.000000070], + ListArray[None, None, [2], [3], [4], [], [], [6]], + ListArray[[c], [c], [c], [c], [c], [c], [c], [c]], + ListArray[[{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [], [], [{x: 8, y: 8}]], ]\ " ); @@ -1929,9 +2075,12 @@ mod tests { // sparse-filled { - let mut query = QueryExpression::new(timeline); - query.view_contents = Some([(entity_path.clone(), None)].into_iter().collect()); - query.sparse_fill_strategy = SparseFillStrategy::LatestAtGlobal; + let query = QueryExpression { + filtered_index, + view_contents: Some([(entity_path.clone(), None)].into_iter().collect()), + sparse_fill_strategy: SparseFillStrategy::LatestAtGlobal, + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -1953,11 +2102,11 @@ mod tests { let expected = unindent::unindent( "\ [ - Int64[None, 10, 20, 30, 40, 50, 60, 65, 70], - Timestamp(Nanosecond, None)[None, 1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, 1970-01-01 00:00:00.000000060, 1970-01-01 00:00:00.000000065, 1970-01-01 00:00:00.000000070], - ListArray[[], None, None, [2], [3], [4], [], [], [6]], - ListArray[[], [c], [c], [c], [c], [c], [], [], [c]], - ListArray[[], [{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [], [], [{x: 8, y: 8}]], + Int64[10, 20, 30, 40, 50, 60, 65, 70], + Timestamp(Nanosecond, None)[1970-01-01 00:00:00.000000010, None, None, None, 1970-01-01 00:00:00.000000050, 1970-01-01 00:00:00.000000060, 1970-01-01 00:00:00.000000065, 1970-01-01 00:00:00.000000070], + ListArray[None, None, [2], [3], [4], [], [], [6]], + ListArray[[c], [c], [c], [c], [c], [c], [c], [c]], + ListArray[[{x: 0, y: 0}], [{x: 1, y: 1}], [{x: 2, y: 2}], [{x: 3, y: 3}], [{x: 4, y: 4}], [], [], [{x: 8, y: 8}]], ]\ " ); @@ -1980,12 +2129,15 @@ mod tests { cache: &query_cache, }; - let timeline = Timeline::new_sequence("frame_nr"); + let filtered_index = Some(Timeline::new_sequence("frame_nr")); let entity_path = EntityPath::from("this/that"); // basic { - let query = QueryExpression::new(timeline); + let query = QueryExpression { + filtered_index, + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -2019,12 +2171,15 @@ mod tests { // with pov { - let mut query = QueryExpression::new(timeline); - query.filtered_point_of_view = Some(ComponentColumnSelector { - entity_path: entity_path.clone(), - component_name: MyPoint::name().to_string(), - join_encoding: Default::default(), - }); + let query = QueryExpression { + filtered_index, + filtered_point_of_view: Some(ComponentColumnSelector { + entity_path: entity_path.clone(), + component_name: MyPoint::name().to_string(), + join_encoding: Default::default(), + }), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -2058,14 +2213,17 @@ mod tests { // with sampling { - let mut query = QueryExpression::new(timeline); - query.using_index_values = Some( - [0, 15, 30, 30, 45, 60, 75, 90] - .into_iter() - .map(TimeInt::new_temporal) - .chain(std::iter::once(TimeInt::STATIC)) - .collect(), - ); + let query = QueryExpression { + filtered_index, + using_index_values: Some( + [0, 15, 30, 30, 45, 60, 75, 90] + .into_iter() + .map(TimeInt::new_temporal) + .chain(std::iter::once(TimeInt::STATIC)) + .collect(), + ), + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); @@ -2099,8 +2257,11 @@ mod tests { // with sparse-fill { - let mut query = QueryExpression::new(timeline); - query.sparse_fill_strategy = SparseFillStrategy::LatestAtGlobal; + let query = QueryExpression { + filtered_index, + sparse_fill_strategy: SparseFillStrategy::LatestAtGlobal, + ..Default::default() + }; eprintln!("{query:#?}:"); let query_handle = query_engine.query(query.clone()); diff --git a/crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs b/crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs index 0fb0cba0ff94..60c8fb775938 100644 --- a/crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs +++ b/crates/viewer/re_space_view_dataframe/src/dataframe_ui.rs @@ -200,7 +200,8 @@ impl<'a> egui_table::TableDelegate for DataframeTableDelegate<'a> { fn prepare(&mut self, info: &egui_table::PrefetchInfo) { re_tracing::profile_function!(); - let timeline = self.query_handle.query().filtered_index; + // TODO(ab): actual static-only support + let filtered_index = self.query_handle.query().filtered_index.unwrap_or_default(); self.query_handle .seek_to_row(info.visible_rows.start as usize); @@ -208,8 +209,12 @@ impl<'a> egui_table::TableDelegate for DataframeTableDelegate<'a> { .take((info.visible_rows.end - info.visible_rows.start) as usize) .collect(); - let data = - RowsDisplayData::try_new(&info.visible_rows, data, self.selected_columns, &timeline); + let data = RowsDisplayData::try_new( + &info.visible_rows, + data, + self.selected_columns, + &filtered_index, + ); self.display_data = data.context("Failed to create display data"); } @@ -253,13 +258,19 @@ impl<'a> egui_table::TableDelegate for DataframeTableDelegate<'a> { } else if cell.row_nr == 1 { let column = &self.selected_columns[cell.col_range.start]; + // TODO(ab): actual static-only support + let filtered_index = + self.query_handle.query().filtered_index.unwrap_or_default(); + // if this column can actually be hidden, then that's the corresponding action let hide_action = match column { - ColumnDescriptor::Time(desc) => (desc.timeline - != self.query_handle.query().filtered_index) - .then(|| HideColumnAction::HideTimeColumn { - timeline_name: *desc.timeline.name(), - }), + ColumnDescriptor::Time(desc) => { + (desc.timeline != filtered_index).then(|| { + HideColumnAction::HideTimeColumn { + timeline_name: *desc.timeline.name(), + } + }) + } ColumnDescriptor::Component(desc) => { Some(HideColumnAction::HideComponentColumn { @@ -331,8 +342,10 @@ impl<'a> egui_table::TableDelegate for DataframeTableDelegate<'a> { .try_decode_time(batch_row_idx) }) .unwrap_or(TimeInt::MAX); - let latest_at_query = - LatestAtQuery::new(self.query_handle.query().filtered_index, timestamp); + + // TODO(ab): actual static-only support + let filtered_index = self.query_handle.query().filtered_index.unwrap_or_default(); + let latest_at_query = LatestAtQuery::new(filtered_index, timestamp); if ui.is_sizing_pass() { ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend); diff --git a/crates/viewer/re_space_view_dataframe/src/space_view_class.rs b/crates/viewer/re_space_view_dataframe/src/space_view_class.rs index 98178d38a619..ec1c2b934de4 100644 --- a/crates/viewer/re_space_view_dataframe/src/space_view_class.rs +++ b/crates/viewer/re_space_view_dataframe/src/space_view_class.rs @@ -145,7 +145,7 @@ mode sets the default time range to _everything_. You can override this in the s let mut dataframe_query = re_chunk_store::QueryExpression { view_contents: Some(view_contents), - filtered_index: view_query.timeline(ctx)?, + filtered_index: Some(view_query.timeline(ctx)?), filtered_index_range: Some(view_query.filter_by_range()?), filtered_point_of_view: view_query.filter_by_event()?, sparse_fill_strategy, diff --git a/rerun_py/src/dataframe.rs b/rerun_py/src/dataframe.rs index 9109dc77adc7..b20654717afe 100644 --- a/rerun_py/src/dataframe.rs +++ b/rerun_py/src/dataframe.rs @@ -457,11 +457,21 @@ impl PyRecordingView { } fn filter_range_sequence(&self, start: i64, end: i64) -> PyResult { - if self.query_expression.filtered_index.typ() != TimeType::Sequence { - return Err(PyValueError::new_err(format!( - "Index for {} is not a sequence.", - self.query_expression.filtered_index.name() - ))); + match self.query_expression.filtered_index.as_ref() { + Some(filtered_index) if filtered_index.typ() != TimeType::Sequence => { + return Err(PyValueError::new_err(format!( + "Index for {} is not a sequence.", + filtered_index.name() + ))); + } + + Some(_) => {} + + None => { + return Err(PyValueError::new_err( + "Specify an index to filter on first.".to_owned(), + )); + } } let start = if let Ok(seq) = re_chunk::TimeInt::try_from(start) { @@ -498,11 +508,21 @@ impl PyRecordingView { } fn filter_range_seconds(&self, start: f64, end: f64) -> PyResult { - if self.query_expression.filtered_index.typ() != TimeType::Time { - return Err(PyValueError::new_err(format!( - "Index for {} is not temporal.", - self.query_expression.filtered_index.name() - ))); + match self.query_expression.filtered_index.as_ref() { + Some(filtered_index) if filtered_index.typ() != TimeType::Time => { + return Err(PyValueError::new_err(format!( + "Index for {} is not temporal.", + filtered_index.name() + ))); + } + + Some(_) => {} + + None => { + return Err(PyValueError::new_err( + "Specify an index to filter on first.".to_owned(), + )); + } } let start = re_sdk::Time::from_seconds_since_epoch(start); @@ -520,11 +540,21 @@ impl PyRecordingView { } fn filter_range_nanos(&self, start: i64, end: i64) -> PyResult { - if self.query_expression.filtered_index.typ() != TimeType::Time { - return Err(PyValueError::new_err(format!( - "Index for {} is not temporal.", - self.query_expression.filtered_index.name() - ))); + match self.query_expression.filtered_index.as_ref() { + Some(filtered_index) if filtered_index.typ() != TimeType::Time => { + return Err(PyValueError::new_err(format!( + "Index for {} is not temporal.", + filtered_index.name() + ))); + } + + Some(_) => {} + + None => { + return Err(PyValueError::new_err( + "Specify an index to filter on first.".to_owned(), + )); + } } let start = re_sdk::Time::from_ns_since_epoch(start); @@ -727,7 +757,7 @@ impl PyRecording { include_semantically_empty_columns: false, include_indicator_columns: false, include_tombstone_columns: false, - filtered_index: timeline.timeline, + filtered_index: Some(timeline.timeline), filtered_index_range: None, filtered_index_values: None, using_index_values: None, From 3cb194bc257c106b16e42f0f91c51ebdd69ea5bd Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Sat, 12 Oct 2024 16:12:55 +0200 Subject: [PATCH 17/33] Dataframe v2: fix debug build performance (#7703) Just some very paranoid debug assertions. Before: ![image](https://github.com/user-attachments/assets/fdf02f02-e7e5-4ddf-807d-6e61a7e5bddb) After: ![image](https://github.com/user-attachments/assets/3ff71e39-c62f-46cb-aa7d-f08360aa3aa2) --- crates/store/re_dataframe/src/query.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/store/re_dataframe/src/query.rs b/crates/store/re_dataframe/src/query.rs index 529a16078694..0b1a897cebe7 100644 --- a/crates/store/re_dataframe/src/query.rs +++ b/crates/store/re_dataframe/src/query.rs @@ -755,7 +755,10 @@ impl QueryHandle<'_> { pub fn num_rows(&self) -> u64 { let num_rows = self.init().unique_index_values.len() as _; - if cfg!(debug_assertions) { + // NOTE: This is too slow to run in practice, even for debug builds. + // Do keep this around though, it does come in handy. + #[allow(clippy::overly_complex_bool_expr)] + if false && cfg!(debug_assertions) { let expected_num_rows = self.engine.query(self.query.clone()).into_iter().count() as u64; assert_eq!(expected_num_rows, num_rows); From 5bc3ba67bfb5a82d105b5336a553a022caa52ecf Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Sat, 12 Oct 2024 16:49:01 +0200 Subject: [PATCH 18/33] Make sure Arrow `filter` and `take` kernels early out where it makes sense (#7704) As expected, `take` didn't. Before: ![image](https://github.com/user-attachments/assets/563067b6-53c0-4828-aaf6-b830f9ea3fcc) After: ![image](https://github.com/user-attachments/assets/1307d019-aa0b-4135-a6a4-8452f8569aa1) * Fixes https://github.com/rerun-io/rerun/issues/7632 --- crates/store/re_chunk/src/util.rs | 22 ++++ crates/store/re_chunk/tests/memory_test.rs | 130 ++++++++++++++++++++- 2 files changed, 151 insertions(+), 1 deletion(-) diff --git a/crates/store/re_chunk/src/util.rs b/crates/store/re_chunk/src/util.rs index 30ed831529bb..375d175e4d80 100644 --- a/crates/store/re_chunk/src/util.rs +++ b/crates/store/re_chunk/src/util.rs @@ -377,6 +377,28 @@ pub fn take_array( "index arrays with validity bits are technically valid, but generally a sign that something went wrong", ); + if indices.len() == array.len() { + let indices = indices.values().as_slice(); + + let starts_at_zero = || indices[0] == O::zero(); + let is_consecutive = || { + indices + .windows(2) + .all(|values| values[1] == values[0] + O::one()) + }; + + if starts_at_zero() && is_consecutive() { + #[allow(clippy::unwrap_used)] + return array + .clone() + .as_any() + .downcast_ref::() + // Unwrap: that's initial type that we got. + .unwrap() + .clone(); + } + } + #[allow(clippy::unwrap_used)] arrow2::compute::take::take(array, indices) // Unwrap: this literally cannot fail. diff --git a/crates/store/re_chunk/tests/memory_test.rs b/crates/store/re_chunk/tests/memory_test.rs index 9a502f675f3d..a23387914f89 100644 --- a/crates/store/re_chunk/tests/memory_test.rs +++ b/crates/store/re_chunk/tests/memory_test.rs @@ -61,7 +61,7 @@ use arrow2::{ }, offset::Offsets as ArrowOffsets, }; -use itertools::Itertools as _; +use itertools::Itertools; #[test] fn filter_does_allocate() { @@ -125,6 +125,72 @@ fn filter_does_allocate() { } } +#[test] +fn filter_empty_or_full_is_noop() { + re_log::setup_logging(); + + const NUM_SCALARS: i64 = 10_000_000; + + let (((unfiltered, unfiltered_size_bytes), (filtered, filtered_size_bytes)), total_size_bytes) = + memory_use(|| { + let unfiltered = memory_use(|| { + let scalars = ArrowPrimitiveArray::from_vec((0..NUM_SCALARS).collect_vec()); + ArrowListArray::::new( + ArrowListArray::::default_datatype(scalars.data_type().clone()), + ArrowOffsets::try_from_lengths( + std::iter::repeat(NUM_SCALARS as usize / 10).take(10), + ) + .unwrap() + .into(), + scalars.to_boxed(), + None, + ) + }); + + let filter = ArrowBooleanArray::from_slice( + std::iter::repeat(true) + .take(unfiltered.0.len()) + .collect_vec(), + ); + let filtered = memory_use(|| re_chunk::util::filter_array(&unfiltered.0, &filter)); + + (unfiltered, filtered) + }); + + eprintln!( + "unfiltered={} filtered={} total={}", + re_format::format_bytes(unfiltered_size_bytes as _), + re_format::format_bytes(filtered_size_bytes as _), + re_format::format_bytes(total_size_bytes as _), + ); + + assert!( + filtered_size_bytes < 1_000, + "filtered array should be the size of a few empty datastructures at most" + ); + + { + let unfiltered = unfiltered + .values() + .as_any() + .downcast_ref::>() + .unwrap(); + let filtered = filtered + .values() + .as_any() + .downcast_ref::>() + .unwrap(); + + assert!( + std::ptr::eq( + unfiltered.values().as_ptr_range().start, + filtered.values().as_ptr_range().start + ), + "whole thing should be a noop -- pointers should match" + ); + } +} + #[test] // TODO(cmc): That's the end goal, but it is simply impossible with `ListArray`'s encoding. // See `Chunk::take_array`'s doc-comment for more information. @@ -191,3 +257,65 @@ fn take_does_not_allocate() { ); } } + +#[test] +fn take_empty_or_full_is_noop() { + re_log::setup_logging(); + + const NUM_SCALARS: i64 = 10_000_000; + + let (((untaken, untaken_size_bytes), (taken, taken_size_bytes)), total_size_bytes) = + memory_use(|| { + let untaken = memory_use(|| { + let scalars = ArrowPrimitiveArray::from_vec((0..NUM_SCALARS).collect_vec()); + ArrowListArray::::new( + ArrowListArray::::default_datatype(scalars.data_type().clone()), + ArrowOffsets::try_from_lengths( + std::iter::repeat(NUM_SCALARS as usize / 10).take(10), + ) + .unwrap() + .into(), + scalars.to_boxed(), + None, + ) + }); + + let indices = ArrowPrimitiveArray::from_vec((0..untaken.0.len() as i32).collect_vec()); + let taken = memory_use(|| re_chunk::util::take_array(&untaken.0, &indices)); + + (untaken, taken) + }); + + eprintln!( + "untaken={} taken={} total={}", + re_format::format_bytes(untaken_size_bytes as _), + re_format::format_bytes(taken_size_bytes as _), + re_format::format_bytes(total_size_bytes as _), + ); + + assert!( + taken_size_bytes < 1_000, + "taken array should be the size of a few empty datastructures at most" + ); + + { + let untaken = untaken + .values() + .as_any() + .downcast_ref::>() + .unwrap(); + let taken = taken + .values() + .as_any() + .downcast_ref::>() + .unwrap(); + + assert!( + std::ptr::eq( + untaken.values().as_ptr_range().start, + taken.values().as_ptr_range().start + ), + "whole thing should be a noop -- pointers should match" + ); + } +} From 2a81c678df710e1ab5855115d10b4215608051fa Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Sat, 12 Oct 2024 17:24:06 +0200 Subject: [PATCH 19/33] Dataframe v2: inline deduped latest logic (#7705) It is impossible for `Chunk::deduped_latest_at_index` to be fast with current Arrow limitations. This PR works around that by inlining that logic into the dataframe walk directly. Before: ![image](https://github.com/user-attachments/assets/44e011fb-4817-4c7b-ae0e-9b80e277f7c9) After: ![image](https://github.com/user-attachments/assets/1b67bdf6-8901-4486-a6cd-d2d4b0f2ea4b) --- crates/store/re_dataframe/src/query.rs | 28 +++++++++++++++++---- scripts/ci/check_large_files_allow_list.txt | 3 ++- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/crates/store/re_dataframe/src/query.rs b/crates/store/re_dataframe/src/query.rs index 0b1a897cebe7..2c4589f715d1 100644 --- a/crates/store/re_dataframe/src/query.rs +++ b/crates/store/re_dataframe/src/query.rs @@ -43,12 +43,12 @@ use crate::{QueryEngine, RecordBatch}; // * [x] sampling support // * [x] clears // * [x] pagination (fast) +// * [x] take kernel duplicates all memory +// * [x] dedupe-latest without allocs/copies +// * [ ] allocate null arrays once // * [ ] overlaps (less dumb) // * [ ] selector-based `filtered_index` // * [ ] configurable cache bypass -// * [ ] allocate null arrays once -// * [ ] take kernel duplicates all memory -// * [ ] dedupe-latest without allocs/copies /// A handle to a dataframe query, ready to be executed. /// @@ -623,7 +623,10 @@ impl QueryHandle<'_> { "the query cache should have already taken care of sorting (and densifying!) the chunk", ); - let chunk = chunk.deduped_latest_on_index(&query.timeline); + // TODO(cmc): That'd be more elegant, but right now there is no way to + // avoid allocations and copies when using Arrow's `ListArray`. + // + // let chunk = chunk.deduped_latest_on_index(&query.timeline); (AtomicU64::default(), chunk) }) @@ -854,13 +857,28 @@ impl QueryHandle<'_> { // have an Arrow ListView at our disposal. let cur_indices = cur_chunk.iter_indices(&state.filtered_index).collect_vec(); let (index_value, cur_row_id) = 'walk: loop { - let Some((index_value, cur_row_id)) = + let Some((mut index_value, mut cur_row_id)) = cur_indices.get(cur_cursor_value as usize).copied() else { continue 'overlaps; }; if index_value == *cur_index_value { + // TODO(cmc): Because of Arrow's `ListArray` limitations, we inline the + // "deduped_latest_on_index" logic here directly, which prevents a lot of + // unnecessary allocations and copies. + while let Some((next_index_value, next_row_id)) = + cur_indices.get(cur_cursor_value as usize + 1).copied() + { + if next_index_value == *cur_index_value { + index_value = next_index_value; + cur_row_id = next_row_id; + cur_cursor_value = cur_cursor.fetch_add(1, Ordering::Relaxed) + 1; + } else { + break; + } + } + break 'walk (index_value, cur_row_id); } diff --git a/scripts/ci/check_large_files_allow_list.txt b/scripts/ci/check_large_files_allow_list.txt index f74a71908930..d4073981b6e9 100644 --- a/scripts/ci/check_large_files_allow_list.txt +++ b/scripts/ci/check_large_files_allow_list.txt @@ -1,6 +1,7 @@ -Cargo.lock CHANGELOG.md +Cargo.lock crates/build/re_types_builder/src/reflection.rs +crates/store/re_dataframe/src/query.rs crates/store/re_types/src/datatypes/tensor_buffer.rs crates/viewer/re_ui/data/Inter-Medium.otf crates/viewer/re_viewer/src/reflection/mod.rs From 160aa120435af7e11f47c9bf009dcbc522127d6a Mon Sep 17 00:00:00 2001 From: rerun-bot <132550499+rerun-bot@users.noreply.github.com> Date: Sat, 12 Oct 2024 17:40:20 +0200 Subject: [PATCH 20/33] Release 0.19.0-alpha.2 (#7702) --- Cargo.lock | 216 +-- Cargo.toml | 120 +- crates/top/rerun/Cargo.toml | 1 + examples/rust/clock/Cargo.toml | 2 +- examples/rust/custom_data_loader/Cargo.toml | 2 +- examples/rust/custom_space_view/Cargo.toml | 2 +- .../rust/custom_store_subscriber/Cargo.toml | 2 +- examples/rust/dna/Cargo.toml | 2 +- examples/rust/extend_viewer_ui/Cargo.toml | 2 +- examples/rust/external_data_loader/Cargo.toml | 2 +- examples/rust/incremental_logging/Cargo.toml | 2 +- examples/rust/log_file/Cargo.toml | 2 +- examples/rust/minimal/Cargo.toml | 2 +- examples/rust/minimal_options/Cargo.toml | 2 +- examples/rust/minimal_serve/Cargo.toml | 2 +- examples/rust/objectron/Cargo.toml | 2 +- examples/rust/raw_mesh/Cargo.toml | 2 +- examples/rust/shared_recording/Cargo.toml | 2 +- examples/rust/spawn_viewer/Cargo.toml | 2 +- examples/rust/stdio/Cargo.toml | 2 +- examples/rust/template/Cargo.toml | 2 +- pixi.lock | 1310 ++++++----------- rerun_cpp/src/rerun/c/sdk_info.h | 2 +- rerun_js/web-viewer-react/README.md | 2 +- rerun_js/web-viewer-react/package.json | 4 +- rerun_js/web-viewer/README.md | 2 +- rerun_js/web-viewer/package.json | 2 +- rerun_notebook/pyproject.toml | 2 +- rerun_py/pyproject.toml | 2 +- rerun_py/rerun_sdk/rerun/__init__.py | 4 +- 30 files changed, 612 insertions(+), 1091 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 390eb91b4723..1e9b03cfa603 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "clock" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -1647,7 +1647,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] name = "custom_data_loader" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "re_build_tools", "rerun", @@ -1655,7 +1655,7 @@ dependencies = [ [[package]] name = "custom_space_view" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "mimalloc", "re_crash_handler", @@ -1665,7 +1665,7 @@ dependencies = [ [[package]] name = "custom_store_subscriber" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "re_build_tools", "rerun", @@ -1786,7 +1786,7 @@ dependencies = [ [[package]] name = "dna" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "itertools 0.13.0", "rand", @@ -2289,7 +2289,7 @@ dependencies = [ [[package]] name = "extend_viewer_ui" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "mimalloc", "re_crash_handler", @@ -2942,7 +2942,7 @@ dependencies = [ [[package]] name = "incremental_logging" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -3356,7 +3356,7 @@ dependencies = [ [[package]] name = "log_benchmark" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -3367,7 +3367,7 @@ dependencies = [ [[package]] name = "log_file" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -3496,14 +3496,14 @@ dependencies = [ [[package]] name = "minimal" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "rerun", ] [[package]] name = "minimal_options" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -3513,7 +3513,7 @@ dependencies = [ [[package]] name = "minimal_serve" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "rerun", ] @@ -4117,7 +4117,7 @@ dependencies = [ [[package]] name = "objectron" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -4326,7 +4326,7 @@ dependencies = [ [[package]] name = "plot_dashboard_stress" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -4801,7 +4801,7 @@ checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" [[package]] name = "raw_mesh" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "bytes", @@ -4840,7 +4840,7 @@ dependencies = [ [[package]] name = "re_analytics" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "crossbeam", "directories", @@ -4886,7 +4886,7 @@ dependencies = [ [[package]] name = "re_blueprint_tree" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "itertools 0.13.0", @@ -4905,14 +4905,14 @@ dependencies = [ [[package]] name = "re_build_info" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "serde", ] [[package]] name = "re_build_tools" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "cargo_metadata 0.18.1", @@ -4925,14 +4925,14 @@ dependencies = [ [[package]] name = "re_case" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "convert_case", ] [[package]] name = "re_chunk" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -4961,7 +4961,7 @@ dependencies = [ [[package]] name = "re_chunk_store" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -4992,7 +4992,7 @@ dependencies = [ [[package]] name = "re_chunk_store_ui" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "egui_extras", @@ -5007,7 +5007,7 @@ dependencies = [ [[package]] name = "re_component_ui" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "egui_extras", @@ -5024,7 +5024,7 @@ dependencies = [ [[package]] name = "re_context_menu" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "egui_tiles", @@ -5045,7 +5045,7 @@ dependencies = [ [[package]] name = "re_crash_handler" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "backtrace", "econtext", @@ -5058,7 +5058,7 @@ dependencies = [ [[package]] name = "re_data_loader" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -5084,7 +5084,7 @@ dependencies = [ [[package]] name = "re_data_source" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "itertools 0.13.0", @@ -5101,7 +5101,7 @@ dependencies = [ [[package]] name = "re_data_ui" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -5130,7 +5130,7 @@ dependencies = [ [[package]] name = "re_dataframe" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "itertools 0.13.0", @@ -5150,7 +5150,7 @@ dependencies = [ [[package]] name = "re_dev_tools" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "argh", @@ -5177,7 +5177,7 @@ dependencies = [ [[package]] name = "re_entity_db" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -5211,21 +5211,21 @@ dependencies = [ [[package]] name = "re_error" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", ] [[package]] name = "re_format" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "num-traits", ] [[package]] name = "re_format_arrow" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "comfy-table", "re_arrow2", @@ -5235,7 +5235,7 @@ dependencies = [ [[package]] name = "re_int_histogram" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "criterion", "insta", @@ -5246,7 +5246,7 @@ dependencies = [ [[package]] name = "re_log" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "env_logger", "js-sys", @@ -5259,7 +5259,7 @@ dependencies = [ [[package]] name = "re_log_encoding" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "criterion", "ehttp", @@ -5285,7 +5285,7 @@ dependencies = [ [[package]] name = "re_log_types" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -5334,7 +5334,7 @@ dependencies = [ [[package]] name = "re_memory" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "backtrace", @@ -5369,7 +5369,7 @@ dependencies = [ [[package]] name = "re_query" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -5400,7 +5400,7 @@ dependencies = [ [[package]] name = "re_renderer" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -5453,7 +5453,7 @@ dependencies = [ [[package]] name = "re_renderer_examples" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -5477,7 +5477,7 @@ dependencies = [ [[package]] name = "re_sdk" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "crossbeam", @@ -5511,7 +5511,7 @@ dependencies = [ [[package]] name = "re_sdk_comms" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "crossbeam", @@ -5527,7 +5527,7 @@ dependencies = [ [[package]] name = "re_selection_panel" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "egui_tiles", @@ -5557,7 +5557,7 @@ dependencies = [ [[package]] name = "re_smart_channel" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "crossbeam", "parking_lot", @@ -5568,7 +5568,7 @@ dependencies = [ [[package]] name = "re_space_view" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "bytemuck", "egui", @@ -5588,7 +5588,7 @@ dependencies = [ [[package]] name = "re_space_view_bar_chart" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "egui_plot", @@ -5606,7 +5606,7 @@ dependencies = [ [[package]] name = "re_space_view_dataframe" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "egui", @@ -5629,7 +5629,7 @@ dependencies = [ [[package]] name = "re_space_view_spatial" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -5668,7 +5668,7 @@ dependencies = [ [[package]] name = "re_space_view_tensor" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "bytemuck", @@ -5692,7 +5692,7 @@ dependencies = [ [[package]] name = "re_space_view_text_document" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "egui_commonmark", @@ -5707,7 +5707,7 @@ dependencies = [ [[package]] name = "re_space_view_text_log" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "egui_extras", @@ -5727,7 +5727,7 @@ dependencies = [ [[package]] name = "re_space_view_time_series" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "egui", "egui_plot", @@ -5749,7 +5749,7 @@ dependencies = [ [[package]] name = "re_string_interner" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "nohash-hasher", @@ -5761,7 +5761,7 @@ dependencies = [ [[package]] name = "re_time_panel" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "criterion", @@ -5786,7 +5786,7 @@ dependencies = [ [[package]] name = "re_tracing" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "puffin", "puffin_http", @@ -5796,7 +5796,7 @@ dependencies = [ [[package]] name = "re_tuid" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "criterion", "document-features", @@ -5808,7 +5808,7 @@ dependencies = [ [[package]] name = "re_types" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "array-init", @@ -5848,7 +5848,7 @@ dependencies = [ [[package]] name = "re_types_blueprint" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "once_cell", "re_arrow2", @@ -5859,7 +5859,7 @@ dependencies = [ [[package]] name = "re_types_builder" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "camino", @@ -5886,7 +5886,7 @@ dependencies = [ [[package]] name = "re_types_core" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "backtrace", @@ -5909,7 +5909,7 @@ dependencies = [ [[package]] name = "re_ui" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "eframe", "egui", @@ -5933,7 +5933,7 @@ dependencies = [ [[package]] name = "re_video" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "crossbeam", "econtext", @@ -5950,7 +5950,7 @@ dependencies = [ [[package]] name = "re_viewer" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -6023,7 +6023,7 @@ dependencies = [ [[package]] name = "re_viewer_context" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "anyhow", @@ -6075,7 +6075,7 @@ dependencies = [ [[package]] name = "re_viewport" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "egui", @@ -6101,7 +6101,7 @@ dependencies = [ [[package]] name = "re_viewport_blueprint" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "egui", @@ -6128,7 +6128,7 @@ dependencies = [ [[package]] name = "re_web_viewer_server" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "document-features", "re_analytics", @@ -6139,7 +6139,7 @@ dependencies = [ [[package]] name = "re_ws_comms" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "bincode", @@ -6232,7 +6232,7 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "rerun" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6271,7 +6271,7 @@ dependencies = [ [[package]] name = "rerun-cli" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "document-features", "mimalloc", @@ -6285,7 +6285,7 @@ dependencies = [ [[package]] name = "rerun-loader-rust-file" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "argh", @@ -6294,7 +6294,7 @@ dependencies = [ [[package]] name = "rerun_c" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "ahash", "infer", @@ -6308,7 +6308,7 @@ dependencies = [ [[package]] name = "rerun_py" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "arrow", "crossbeam", @@ -6412,7 +6412,7 @@ dependencies = [ [[package]] name = "roundtrip_annotation_context" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6422,7 +6422,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows2d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6432,7 +6432,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows3d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6442,7 +6442,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes2d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6452,7 +6452,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes3d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6462,7 +6462,7 @@ dependencies = [ [[package]] name = "roundtrip_depth_image" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6473,7 +6473,7 @@ dependencies = [ [[package]] name = "roundtrip_disconnected_space" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6483,7 +6483,7 @@ dependencies = [ [[package]] name = "roundtrip_image" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6496,7 +6496,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips2d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6506,7 +6506,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips3d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6516,7 +6516,7 @@ dependencies = [ [[package]] name = "roundtrip_pinhole" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6526,7 +6526,7 @@ dependencies = [ [[package]] name = "roundtrip_points2d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6536,7 +6536,7 @@ dependencies = [ [[package]] name = "roundtrip_points3d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6546,7 +6546,7 @@ dependencies = [ [[package]] name = "roundtrip_segmentation_image" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6557,7 +6557,7 @@ dependencies = [ [[package]] name = "roundtrip_tensor" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6568,7 +6568,7 @@ dependencies = [ [[package]] name = "roundtrip_text_document" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6578,7 +6578,7 @@ dependencies = [ [[package]] name = "roundtrip_text_log" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6588,7 +6588,7 @@ dependencies = [ [[package]] name = "roundtrip_transform3d" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6598,7 +6598,7 @@ dependencies = [ [[package]] name = "roundtrip_view_coordinates" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6608,7 +6608,7 @@ dependencies = [ [[package]] name = "roundtrip_visible_time_ranges" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -6624,7 +6624,7 @@ checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" [[package]] name = "run_wasm" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "cargo-run-wasm", "pico-args", @@ -6905,7 +6905,7 @@ dependencies = [ [[package]] name = "shared_recording" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "rerun", ] @@ -7041,7 +7041,7 @@ dependencies = [ [[package]] name = "snippets" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "itertools 0.13.0", "ndarray 0.16.1", @@ -7064,7 +7064,7 @@ dependencies = [ [[package]] name = "spawn_viewer" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "rerun", ] @@ -7098,7 +7098,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stdio" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "rerun", ] @@ -7194,7 +7194,7 @@ dependencies = [ [[package]] name = "template" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "rerun", ] @@ -7210,7 +7210,7 @@ dependencies = [ [[package]] name = "test_api" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -7225,7 +7225,7 @@ dependencies = [ [[package]] name = "test_data_density_graph" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "rand", @@ -7235,7 +7235,7 @@ dependencies = [ [[package]] name = "test_image_memory" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "mimalloc", "re_format", @@ -7244,7 +7244,7 @@ dependencies = [ [[package]] name = "test_pinhole_projection" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", @@ -7255,7 +7255,7 @@ dependencies = [ [[package]] name = "test_send_columns" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "re_chunk", "rerun", @@ -7263,7 +7263,7 @@ dependencies = [ [[package]] name = "test_ui_wakeup" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index 4865b52f5196..ff5e14fad56a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ include = ["../../LICENSE-APACHE", "../../LICENSE-MIT", "**/*.rs", "Cargo.toml"] license = "MIT OR Apache-2.0" repository = "https://github.com/rerun-io/rerun" rust-version = "1.79" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" [workspace.dependencies] # When using alpha-release, always use exact version, e.g. `version = "=0.x.y-alpha.z" @@ -34,73 +34,73 @@ version = "0.19.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.19.0-alpha.1", default-features = false } -re_build_tools = { path = "crates/build/re_build_tools", version = "=0.19.0-alpha.1", default-features = false } -re_dev_tools = { path = "crates/build/re_dev_tools", version = "=0.19.0-alpha.1", default-features = false } -re_types_builder = { path = "crates/build/re_types_builder", version = "=0.19.0-alpha.1", default-features = false } +re_build_info = { path = "crates/build/re_build_info", version = "=0.19.0-alpha.2", default-features = false } +re_build_tools = { path = "crates/build/re_build_tools", version = "=0.19.0-alpha.2", default-features = false } +re_dev_tools = { path = "crates/build/re_dev_tools", version = "=0.19.0-alpha.2", default-features = false } +re_types_builder = { path = "crates/build/re_types_builder", version = "=0.19.0-alpha.2", default-features = false } # crates/store: -re_chunk = { path = "crates/store/re_chunk", version = "=0.19.0-alpha.1", default-features = false } -re_chunk_store = { path = "crates/store/re_chunk_store", version = "=0.19.0-alpha.1", default-features = false } -re_data_loader = { path = "crates/store/re_data_loader", version = "=0.19.0-alpha.1", default-features = false } -re_data_source = { path = "crates/store/re_data_source", version = "=0.19.0-alpha.1", default-features = false } -re_dataframe = { path = "crates/store/re_dataframe", version = "=0.19.0-alpha.1", default-features = false } -re_entity_db = { path = "crates/store/re_entity_db", version = "=0.19.0-alpha.1", default-features = false } -re_format_arrow = { path = "crates/store/re_format_arrow", version = "=0.19.0-alpha.1", default-features = false } -re_log_encoding = { path = "crates/store/re_log_encoding", version = "=0.19.0-alpha.1", default-features = false } -re_log_types = { path = "crates/store/re_log_types", version = "=0.19.0-alpha.1", default-features = false } -re_query = { path = "crates/store/re_query", version = "=0.19.0-alpha.1", default-features = false } -re_sdk_comms = { path = "crates/store/re_sdk_comms", version = "=0.19.0-alpha.1", default-features = false } -re_types = { path = "crates/store/re_types", version = "=0.19.0-alpha.1", default-features = false } -re_types_blueprint = { path = "crates/store/re_types_blueprint", version = "=0.19.0-alpha.1", default-features = false } -re_types_core = { path = "crates/store/re_types_core", version = "=0.19.0-alpha.1", default-features = false } -re_video = { path = "crates/store/re_video", version = "=0.19.0-alpha.1", default-features = false } -re_ws_comms = { path = "crates/store/re_ws_comms", version = "=0.19.0-alpha.1", default-features = false } +re_chunk = { path = "crates/store/re_chunk", version = "=0.19.0-alpha.2", default-features = false } +re_chunk_store = { path = "crates/store/re_chunk_store", version = "=0.19.0-alpha.2", default-features = false } +re_data_loader = { path = "crates/store/re_data_loader", version = "=0.19.0-alpha.2", default-features = false } +re_data_source = { path = "crates/store/re_data_source", version = "=0.19.0-alpha.2", default-features = false } +re_dataframe = { path = "crates/store/re_dataframe", version = "=0.19.0-alpha.2", default-features = false } +re_entity_db = { path = "crates/store/re_entity_db", version = "=0.19.0-alpha.2", default-features = false } +re_format_arrow = { path = "crates/store/re_format_arrow", version = "=0.19.0-alpha.2", default-features = false } +re_log_encoding = { path = "crates/store/re_log_encoding", version = "=0.19.0-alpha.2", default-features = false } +re_log_types = { path = "crates/store/re_log_types", version = "=0.19.0-alpha.2", default-features = false } +re_query = { path = "crates/store/re_query", version = "=0.19.0-alpha.2", default-features = false } +re_sdk_comms = { path = "crates/store/re_sdk_comms", version = "=0.19.0-alpha.2", default-features = false } +re_types = { path = "crates/store/re_types", version = "=0.19.0-alpha.2", default-features = false } +re_types_blueprint = { path = "crates/store/re_types_blueprint", version = "=0.19.0-alpha.2", default-features = false } +re_types_core = { path = "crates/store/re_types_core", version = "=0.19.0-alpha.2", default-features = false } +re_video = { path = "crates/store/re_video", version = "=0.19.0-alpha.2", default-features = false } +re_ws_comms = { path = "crates/store/re_ws_comms", version = "=0.19.0-alpha.2", default-features = false } # crates/top: -re_sdk = { path = "crates/top/re_sdk", version = "=0.19.0-alpha.1", default-features = false } -rerun = { path = "crates/top/rerun", version = "=0.19.0-alpha.1", default-features = false } -rerun_c = { path = "crates/top/rerun_c", version = "=0.19.0-alpha.1", default-features = false } -rerun-cli = { path = "crates/top/rerun-cli", version = "=0.19.0-alpha.1", default-features = false } +re_sdk = { path = "crates/top/re_sdk", version = "=0.19.0-alpha.2", default-features = false } +rerun = { path = "crates/top/rerun", version = "=0.19.0-alpha.2", default-features = false } +rerun_c = { path = "crates/top/rerun_c", version = "=0.19.0-alpha.2", default-features = false } +rerun-cli = { path = "crates/top/rerun-cli", version = "=0.19.0-alpha.2", default-features = false } # crates/utils: -re_analytics = { path = "crates/utils/re_analytics", version = "=0.19.0-alpha.1", default-features = false } -re_case = { path = "crates/utils/re_case", version = "=0.19.0-alpha.1", default-features = false } -re_crash_handler = { path = "crates/utils/re_crash_handler", version = "=0.19.0-alpha.1", default-features = false } -re_error = { path = "crates/utils/re_error", version = "=0.19.0-alpha.1", default-features = false } -re_format = { path = "crates/utils/re_format", version = "=0.19.0-alpha.1", default-features = false } -re_int_histogram = { path = "crates/utils/re_int_histogram", version = "=0.19.0-alpha.1", default-features = false } -re_log = { path = "crates/utils/re_log", version = "=0.19.0-alpha.1", default-features = false } -re_memory = { path = "crates/utils/re_memory", version = "=0.19.0-alpha.1", default-features = false } -re_smart_channel = { path = "crates/utils/re_smart_channel", version = "=0.19.0-alpha.1", default-features = false } -re_string_interner = { path = "crates/utils/re_string_interner", version = "=0.19.0-alpha.1", default-features = false } -re_tracing = { path = "crates/utils/re_tracing", version = "=0.19.0-alpha.1", default-features = false } -re_tuid = { path = "crates/utils/re_tuid", version = "=0.19.0-alpha.1", default-features = false } +re_analytics = { path = "crates/utils/re_analytics", version = "=0.19.0-alpha.2", default-features = false } +re_case = { path = "crates/utils/re_case", version = "=0.19.0-alpha.2", default-features = false } +re_crash_handler = { path = "crates/utils/re_crash_handler", version = "=0.19.0-alpha.2", default-features = false } +re_error = { path = "crates/utils/re_error", version = "=0.19.0-alpha.2", default-features = false } +re_format = { path = "crates/utils/re_format", version = "=0.19.0-alpha.2", default-features = false } +re_int_histogram = { path = "crates/utils/re_int_histogram", version = "=0.19.0-alpha.2", default-features = false } +re_log = { path = "crates/utils/re_log", version = "=0.19.0-alpha.2", default-features = false } +re_memory = { path = "crates/utils/re_memory", version = "=0.19.0-alpha.2", default-features = false } +re_smart_channel = { path = "crates/utils/re_smart_channel", version = "=0.19.0-alpha.2", default-features = false } +re_string_interner = { path = "crates/utils/re_string_interner", version = "=0.19.0-alpha.2", default-features = false } +re_tracing = { path = "crates/utils/re_tracing", version = "=0.19.0-alpha.2", default-features = false } +re_tuid = { path = "crates/utils/re_tuid", version = "=0.19.0-alpha.2", default-features = false } # crates/viewer: -re_blueprint_tree = { path = "crates/viewer/re_blueprint_tree", version = "=0.19.0-alpha.1", default-features = false } -re_component_ui = { path = "crates/viewer/re_component_ui", version = "=0.19.0-alpha.1", default-features = false } -re_context_menu = { path = "crates/viewer/re_context_menu", version = "=0.19.0-alpha.1", default-features = false } -re_data_ui = { path = "crates/viewer/re_data_ui", version = "=0.19.0-alpha.1", default-features = false } -re_chunk_store_ui = { path = "crates/viewer/re_chunk_store_ui", version = "=0.19.0-alpha.1", default-features = false } -re_renderer = { path = "crates/viewer/re_renderer", version = "=0.19.0-alpha.1", default-features = false } -re_renderer_examples = { path = "crates/viewer/re_renderer_examples", version = "=0.19.0-alpha.1", default-features = false } -re_selection_panel = { path = "crates/viewer/re_selection_panel", version = "=0.19.0-alpha.1", default-features = false } -re_space_view = { path = "crates/viewer/re_space_view", version = "=0.19.0-alpha.1", default-features = false } -re_space_view_bar_chart = { path = "crates/viewer/re_space_view_bar_chart", version = "=0.19.0-alpha.1", default-features = false } -re_space_view_dataframe = { path = "crates/viewer/re_space_view_dataframe", version = "=0.19.0-alpha.1", default-features = false } -re_space_view_spatial = { path = "crates/viewer/re_space_view_spatial", version = "=0.19.0-alpha.1", default-features = false } -re_space_view_tensor = { path = "crates/viewer/re_space_view_tensor", version = "=0.19.0-alpha.1", default-features = false } -re_space_view_text_document = { path = "crates/viewer/re_space_view_text_document", version = "=0.19.0-alpha.1", default-features = false } -re_space_view_text_log = { path = "crates/viewer/re_space_view_text_log", version = "=0.19.0-alpha.1", default-features = false } -re_space_view_time_series = { path = "crates/viewer/re_space_view_time_series", version = "=0.19.0-alpha.1", default-features = false } -re_time_panel = { path = "crates/viewer/re_time_panel", version = "=0.19.0-alpha.1", default-features = false } -re_ui = { path = "crates/viewer/re_ui", version = "=0.19.0-alpha.1", default-features = false } -re_viewer = { path = "crates/viewer/re_viewer", version = "=0.19.0-alpha.1", default-features = false } -re_viewer_context = { path = "crates/viewer/re_viewer_context", version = "=0.19.0-alpha.1", default-features = false } -re_viewport = { path = "crates/viewer/re_viewport", version = "=0.19.0-alpha.1", default-features = false } -re_viewport_blueprint = { path = "crates/viewer/re_viewport_blueprint", version = "=0.19.0-alpha.1", default-features = false } -re_web_viewer_server = { path = "crates/viewer/re_web_viewer_server", version = "=0.19.0-alpha.1", default-features = false } +re_blueprint_tree = { path = "crates/viewer/re_blueprint_tree", version = "=0.19.0-alpha.2", default-features = false } +re_component_ui = { path = "crates/viewer/re_component_ui", version = "=0.19.0-alpha.2", default-features = false } +re_context_menu = { path = "crates/viewer/re_context_menu", version = "=0.19.0-alpha.2", default-features = false } +re_data_ui = { path = "crates/viewer/re_data_ui", version = "=0.19.0-alpha.2", default-features = false } +re_chunk_store_ui = { path = "crates/viewer/re_chunk_store_ui", version = "=0.19.0-alpha.2", default-features = false } +re_renderer = { path = "crates/viewer/re_renderer", version = "=0.19.0-alpha.2", default-features = false } +re_renderer_examples = { path = "crates/viewer/re_renderer_examples", version = "=0.19.0-alpha.2", default-features = false } +re_selection_panel = { path = "crates/viewer/re_selection_panel", version = "=0.19.0-alpha.2", default-features = false } +re_space_view = { path = "crates/viewer/re_space_view", version = "=0.19.0-alpha.2", default-features = false } +re_space_view_bar_chart = { path = "crates/viewer/re_space_view_bar_chart", version = "=0.19.0-alpha.2", default-features = false } +re_space_view_dataframe = { path = "crates/viewer/re_space_view_dataframe", version = "=0.19.0-alpha.2", default-features = false } +re_space_view_spatial = { path = "crates/viewer/re_space_view_spatial", version = "=0.19.0-alpha.2", default-features = false } +re_space_view_tensor = { path = "crates/viewer/re_space_view_tensor", version = "=0.19.0-alpha.2", default-features = false } +re_space_view_text_document = { path = "crates/viewer/re_space_view_text_document", version = "=0.19.0-alpha.2", default-features = false } +re_space_view_text_log = { path = "crates/viewer/re_space_view_text_log", version = "=0.19.0-alpha.2", default-features = false } +re_space_view_time_series = { path = "crates/viewer/re_space_view_time_series", version = "=0.19.0-alpha.2", default-features = false } +re_time_panel = { path = "crates/viewer/re_time_panel", version = "=0.19.0-alpha.2", default-features = false } +re_ui = { path = "crates/viewer/re_ui", version = "=0.19.0-alpha.2", default-features = false } +re_viewer = { path = "crates/viewer/re_viewer", version = "=0.19.0-alpha.2", default-features = false } +re_viewer_context = { path = "crates/viewer/re_viewer_context", version = "=0.19.0-alpha.2", default-features = false } +re_viewport = { path = "crates/viewer/re_viewport", version = "=0.19.0-alpha.2", default-features = false } +re_viewport_blueprint = { path = "crates/viewer/re_viewport_blueprint", version = "=0.19.0-alpha.2", default-features = false } +re_web_viewer_server = { path = "crates/viewer/re_web_viewer_server", version = "=0.19.0-alpha.2", default-features = false } # Rerun crates in other repos: ewebsock = "0.6.0" diff --git a/crates/top/rerun/Cargo.toml b/crates/top/rerun/Cargo.toml index a6fe1b87e346..fb7214aad752 100644 --- a/crates/top/rerun/Cargo.toml +++ b/crates/top/rerun/Cargo.toml @@ -159,6 +159,7 @@ unindent = { workspace = true, optional = true } [build-dependencies] re_build_tools.workspace = true + [package.metadata.cargo-machete] # We only depend on re_video so we can enable extra features for it ignored = ["re_video"] diff --git a/examples/rust/clock/Cargo.toml b/examples/rust/clock/Cargo.toml index e8fa32b0f7a6..0a0923cc4de7 100644 --- a/examples/rust/clock/Cargo.toml +++ b/examples/rust/clock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clock" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_data_loader/Cargo.toml b/examples/rust/custom_data_loader/Cargo.toml index 0c0e2e7ea735..f0bd49bb0f5d 100644 --- a/examples/rust/custom_data_loader/Cargo.toml +++ b/examples/rust/custom_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_data_loader" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index 7d715d78e10d..0773377d1a68 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_space_view" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_store_subscriber/Cargo.toml b/examples/rust/custom_store_subscriber/Cargo.toml index a841bb43e02f..eb4fc8769b16 100644 --- a/examples/rust/custom_store_subscriber/Cargo.toml +++ b/examples/rust/custom_store_subscriber/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_store_subscriber" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml index 7d871018ffc4..544cea3a56a1 100644 --- a/examples/rust/dna/Cargo.toml +++ b/examples/rust/dna/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dna" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml index a050d355ce99..71ab4655860c 100644 --- a/examples/rust/extend_viewer_ui/Cargo.toml +++ b/examples/rust/extend_viewer_ui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extend_viewer_ui" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/external_data_loader/Cargo.toml b/examples/rust/external_data_loader/Cargo.toml index 6867c63fa80a..f2af2a8a681e 100644 --- a/examples/rust/external_data_loader/Cargo.toml +++ b/examples/rust/external_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rerun-loader-rust-file" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml index 58ba5169f39f..7f9a7047202f 100644 --- a/examples/rust/incremental_logging/Cargo.toml +++ b/examples/rust/incremental_logging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "incremental_logging" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml index d3aef9e3190f..65bbcbdf26b1 100644 --- a/examples/rust/log_file/Cargo.toml +++ b/examples/rust/log_file/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "log_file" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal/Cargo.toml b/examples/rust/minimal/Cargo.toml index 011a749b57ce..3f91a4322344 100644 --- a/examples/rust/minimal/Cargo.toml +++ b/examples/rust/minimal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_options/Cargo.toml b/examples/rust/minimal_options/Cargo.toml index 03d97468a535..3152e86a7ce9 100644 --- a/examples/rust/minimal_options/Cargo.toml +++ b/examples/rust/minimal_options/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_options" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml index 326312b29b5d..4002f002102b 100644 --- a/examples/rust/minimal_serve/Cargo.toml +++ b/examples/rust/minimal_serve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_serve" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/objectron/Cargo.toml b/examples/rust/objectron/Cargo.toml index 8961a95547c8..7e0357ffb9d0 100644 --- a/examples/rust/objectron/Cargo.toml +++ b/examples/rust/objectron/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "objectron" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/raw_mesh/Cargo.toml b/examples/rust/raw_mesh/Cargo.toml index 192a1ae6f331..90ad91fa6963 100644 --- a/examples/rust/raw_mesh/Cargo.toml +++ b/examples/rust/raw_mesh/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "raw_mesh" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/shared_recording/Cargo.toml b/examples/rust/shared_recording/Cargo.toml index 96a6f5265b89..e41079128429 100644 --- a/examples/rust/shared_recording/Cargo.toml +++ b/examples/rust/shared_recording/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared_recording" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/spawn_viewer/Cargo.toml b/examples/rust/spawn_viewer/Cargo.toml index a9ecdfa153b1..e75a1478dcf2 100644 --- a/examples/rust/spawn_viewer/Cargo.toml +++ b/examples/rust/spawn_viewer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spawn_viewer" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/stdio/Cargo.toml b/examples/rust/stdio/Cargo.toml index c635a9a4cd75..698301a565ee 100644 --- a/examples/rust/stdio/Cargo.toml +++ b/examples/rust/stdio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stdio" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/template/Cargo.toml b/examples/rust/template/Cargo.toml index c23e8f0d34de..14b9fadb2e41 100644 --- a/examples/rust/template/Cargo.toml +++ b/examples/rust/template/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "template" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/pixi.lock b/pixi.lock index 8561a153649f..158f14e6ffd4 100644 --- a/pixi.lock +++ b/pixi.lock @@ -2469,7 +2469,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/ad/96/138484302b8ec9a69cdf65e8d4ab47a640a3b1a8ea3c437e1da3e1a5a6b8/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/32/63/ed228892adad313aab0d0f9261241e7bf1efe36730a2788ad424bcad00ca/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/89/bb/80c9c98d887c855710fd31fc5ae5574133e98203b3475b07579251803662/scipy-1.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: git+https://github.com/facebookresearch/segment-anything.git@526fd066dea338ba2ca08886853bd37ffd6a8aec + - pypi: git+https://github.com/facebookresearch/segment-anything.git@dca509fe793f601edb92606367a655c15ac00fdf - pypi: https://files.pythonhosted.org/packages/40/b0/4562db6223154aa4e22f939003cb92514c79f3d4dccca3444253fd17f902/Send2Trash-1.8.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ed/a8/c8b0f1a165e161247caf0fc265d61de3c4ea27d7c313c7ebfb1c4f6ddea4/shapely-2.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/70/c1/816573ae91aebf06a0fefd8ea30ca43127aa58e68684d2ddfe17c8457afb/simplejson-3.19.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl @@ -2882,7 +2882,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b8/2e/3a949995f8fc2a65b15a4964373e26c5601cb2ea68f36b115571663e7a38/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/c1/f8/fd3fa610cac686952d8c78b8b44cf5263c6c03885bd8e5d5819c684b44e8/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/6c/bb/f44e22697740893ffa84239ca3766bdb908c1c7135ebb272d5bd4bdc33e2/scipy-1.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - - pypi: git+https://github.com/facebookresearch/segment-anything.git@526fd066dea338ba2ca08886853bd37ffd6a8aec + - pypi: git+https://github.com/facebookresearch/segment-anything.git@dca509fe793f601edb92606367a655c15ac00fdf - pypi: https://files.pythonhosted.org/packages/40/b0/4562db6223154aa4e22f939003cb92514c79f3d4dccca3444253fd17f902/Send2Trash-1.8.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7e/4e/4e83b9f3d7f0ce523c92bdf3dfe0292738d8ad2b589971390d6205bc843e/shapely-2.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/a0/d8/f9e822563d5ccf9e199719a64db221f942c9a04cce17140c4b4fe51a25fc/simplejson-3.19.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl @@ -3266,7 +3266,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/90/e3/564beb0c78bf83018a146dfcdc959c99c10a0d136480b932a350c852adbc/scikit_image-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/03/86/ab9f95e338c5ef5b4e79463ee91e55aae553213835e59bf038bc0cc21bf8/scikit_learn-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/10/55/d6096721c0f0d7e7369da9660a854c14e6379ab7aba603ea5d492d77fa23/scipy-1.14.0-cp311-cp311-macosx_10_9_x86_64.whl - - pypi: git+https://github.com/facebookresearch/segment-anything.git@526fd066dea338ba2ca08886853bd37ffd6a8aec + - pypi: git+https://github.com/facebookresearch/segment-anything.git@dca509fe793f601edb92606367a655c15ac00fdf - pypi: https://files.pythonhosted.org/packages/40/b0/4562db6223154aa4e22f939003cb92514c79f3d4dccca3444253fd17f902/Send2Trash-1.8.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/3d/0d3ab80860cda6afbce9736fa1f091f452092d344fdd4e3c65e5fe7b1111/shapely-2.0.5-cp311-cp311-macosx_10_9_x86_64.whl - pypi: https://files.pythonhosted.org/packages/bc/eb/2bd4a6ec98329158f6855520596e9f2e521e2239e292d43fe1c58cf83a9b/simplejson-3.19.2-cp311-cp311-macosx_10_9_x86_64.whl @@ -3655,7 +3655,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/3c/f6/be8b16d8ab6ebf19057877c2aec905cbd438dd92ca64b8efe9e9af008fa3/scikit_image-0.24.0-cp311-cp311-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/7d/d7/fb80c63062b60b1fa5dcb2d4dd3a4e83bd8c68cdc83cf6ff8c016228f184/scikit_learn-1.5.1-cp311-cp311-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/56/95/1a3a04b5facab8287325ad2335dbb6b78b98d73690c832099c9c498f7a4d/scipy-1.14.0-cp311-cp311-macosx_12_0_arm64.whl - - pypi: git+https://github.com/facebookresearch/segment-anything.git@526fd066dea338ba2ca08886853bd37ffd6a8aec + - pypi: git+https://github.com/facebookresearch/segment-anything.git@dca509fe793f601edb92606367a655c15ac00fdf - pypi: https://files.pythonhosted.org/packages/40/b0/4562db6223154aa4e22f939003cb92514c79f3d4dccca3444253fd17f902/Send2Trash-1.8.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/80/68/6b51b7587547f6bbd0965cf957505a0ebec93510e840572a983003b3a0a9/shapely-2.0.5-cp311-cp311-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/53/a0/4430915cac272de9af75287f566cd1f06dffb69b3e9fa24b3c16b066470b/simplejson-3.19.2-cp311-cp311-macosx_11_0_arm64.whl @@ -4036,7 +4036,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/50/b2/d5e97115733e2dc657e99868ae0237705b79d0c81f6ced21b8f0799a30d1/scikit_image-0.24.0-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/5d/55/0403bf2031250ac982c8053397889fbc5a3a2b3798b913dae4f51c3af6a4/scikit_learn-1.5.1-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/91/1d/0484130df7e33e044da88a091827d6441b77f907075bf7bbe145857d6590/scipy-1.14.0-cp311-cp311-win_amd64.whl - - pypi: git+https://github.com/facebookresearch/segment-anything.git@526fd066dea338ba2ca08886853bd37ffd6a8aec + - pypi: git+https://github.com/facebookresearch/segment-anything.git@dca509fe793f601edb92606367a655c15ac00fdf - pypi: https://files.pythonhosted.org/packages/40/b0/4562db6223154aa4e22f939003cb92514c79f3d4dccca3444253fd17f902/Send2Trash-1.8.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ec/1b/092fff53cbeced411eed2717592e31cadd3e52f0ebaba5f2df3f34913f96/shapely-2.0.5-cp311-cp311-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/b6/8e/3e12d122dfdf549a8d12eaf39954ee39f2027060aa38b63430f8ab3244e7/simplejson-3.19.2-cp311-cp311-win_amd64.whl @@ -12172,21 +12172,6 @@ packages: - tqdm - trimesh editable: true -- kind: pypi - name: arkit-scenes - version: 0.1.0 - path: examples/python/arkit_scenes - sha256: 1ea1defa403966ebbc7e54ff7b92f65fdb6c98ee3e242d8af0be46023ed87961 - requires_dist: - - matplotlib - - numpy - - opencv-python - - pandas - - rerun-sdk - - scipy - - tqdm - - trimesh - editable: true - kind: pypi name: arrow version: 1.3.0 @@ -14576,20 +14561,6 @@ packages: - jinja2 ; extra == 'compiler' - protobuf ; extra == 'compiler' requires_python: '>=3.6' -- kind: pypi - name: betterproto - version: 1.2.5 - url: https://files.pythonhosted.org/packages/ff/2e/abfed7a721928e14aeb900182ff695be474c4ee5f07ef0874cc5ecd5b0b1/betterproto-1.2.5.tar.gz - sha256: 74a3ab34646054f674d236d1229ba8182dc2eae86feb249b8590ef496ce9803d - requires_dist: - - grpclib - - stringcase - - dataclasses ; python_version < '3.7' - - backports-datetime-fromisoformat ; python_version < '3.7' - - black ; extra == 'compiler' - - jinja2 ; extra == 'compiler' - - protobuf ; extra == 'compiler' - requires_python: '>=3.6' - kind: conda name: binaryen version: '117' @@ -14770,8 +14741,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl - sha256: d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c + url: https://files.pythonhosted.org/packages/74/ce/e8eec1a77edbfa982bee3b5460dcdd4fe0e4e3165fc15d8ec44d04da7776/black-24.4.2-cp311-cp311-win_amd64.whl + sha256: 7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14790,8 +14761,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/74/ce/e8eec1a77edbfa982bee3b5460dcdd4fe0e4e3165fc15d8ec44d04da7776/black-24.4.2-cp311-cp311-win_amd64.whl - sha256: 7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 + url: https://files.pythonhosted.org/packages/9b/f7/591d601c3046ceb65b97291dfe87fa25124cffac3d97aaaba89d0f0d7bdf/black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14810,8 +14781,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/9b/f7/591d601c3046ceb65b97291dfe87fa25124cffac3d97aaaba89d0f0d7bdf/black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 + url: https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl + sha256: d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14830,8 +14801,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/c5/48/34176b522e8cff4620a5d96c2e323ff2413f574870eb25efa8025885e028/black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb + url: https://files.pythonhosted.org/packages/c9/17/5e0036b265bbf6bc44970d93d48febcbc03701b671db3c9603fd43ebc616/black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14850,8 +14821,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/c9/17/5e0036b265bbf6bc44970d93d48febcbc03701b671db3c9603fd43ebc616/black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c + url: https://files.pythonhosted.org/packages/c5/48/34176b522e8cff4620a5d96c2e323ff2413f574870eb25efa8025885e028/black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14886,26 +14857,6 @@ packages: - numpy - rerun-sdk editable: true -- kind: pypi - name: blueprint - version: 0.1.0 - path: examples/python/blueprint - sha256: d9a358e5994ec1e9144942903e46148b16825344cddc19e7188b285f59bc61c1 - requires_dist: - - numpy - - rerun-sdk - editable: true -- kind: pypi - name: blueprint-stocks - version: 0.1.0 - path: examples/python/blueprint_stocks - sha256: 7c8b6805f08610837014175d9d0212815a91c3197756cdbbce836a2f15e40eea - requires_dist: - - humanize - - rerun-sdk - - yfinance - requires_python: '>=3.8' - editable: true - kind: pypi name: blueprint-stocks version: 0.1.0 @@ -15584,8 +15535,8 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 requires_dist: - pycparser requires_python: '>=3.8' @@ -15600,48 +15551,48 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 requires_python: '>=3.7.0' - kind: conda name: clang @@ -17011,15 +16962,6 @@ packages: - numpy - rerun-sdk editable: true -- kind: pypi - name: clock - version: 0.1.0 - path: examples/python/clock - sha256: 1ae48a7222b2fc2bd9942a31bb48fefb34225a946859ad95c25ad00bfb754cd7 - requires_dist: - - numpy - - rerun-sdk - editable: true - kind: conda name: cmake version: 3.27.6 @@ -17252,8 +17194,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 + url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl + sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17276,8 +17218,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/98/72/ae1e8518a2fe75980598a2716e392c7642b70b6a5605fc925426007b0f49/contourpy-1.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6150ffa5c767bc6332df27157d95442c379b7dce3a38dff89c0f39b63275696f + url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17300,8 +17242,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 + url: https://files.pythonhosted.org/packages/98/72/ae1e8518a2fe75980598a2716e392c7642b70b6a5605fc925426007b0f49/contourpy-1.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6150ffa5c767bc6332df27157d95442c379b7dce3a38dff89c0f39b63275696f requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17324,8 +17266,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl - sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 + url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17385,27 +17327,11 @@ packages: - rerun-sdk requires_python: '>=3.10' editable: true -- kind: pypi - name: controlnet - version: 0.1.0 - path: examples/python/controlnet - sha256: 8ae055c0b8b0dd7757e4e666f6163172859044d4090830aecbec3460cdb318ee - requires_dist: - - accelerate - - opencv-python - - pillow - - diffusers==0.27.2 - - numpy - - torch==2.2.2 - - transformers - - rerun-sdk - requires_python: '>=3.10' - editable: true - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl - sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17432,8 +17358,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb + url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl + sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17460,8 +17386,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 + url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17488,8 +17414,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl - sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b + url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17516,8 +17442,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d + url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl + sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17732,14 +17658,14 @@ packages: - kind: pypi name: debugpy version: 1.8.2 - url: https://files.pythonhosted.org/packages/4f/d6/04ae52227ab7c1d43b729d5ae75ebd592df56c55d4e4dfa30ba173096b0f/debugpy-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: acdf39855f65c48ac9667b2801234fc64d46778021efac2de7e50907ab90c634 + url: https://files.pythonhosted.org/packages/b4/32/dd0707c8557f99496811763c5333ea87bcec1eb233c1efa324c9a8082bff/debugpy-1.8.2-py2.py3-none-any.whl + sha256: 16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca requires_python: '>=3.8' - kind: pypi name: debugpy version: 1.8.2 - url: https://files.pythonhosted.org/packages/b4/32/dd0707c8557f99496811763c5333ea87bcec1eb233c1efa324c9a8082bff/debugpy-1.8.2-py2.py3-none-any.whl - sha256: 16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca + url: https://files.pythonhosted.org/packages/4f/d6/04ae52227ab7c1d43b729d5ae75ebd592df56c55d4e4dfa30ba173096b0f/debugpy-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: acdf39855f65c48ac9667b2801234fc64d46778021efac2de7e50907ab90c634 requires_python: '>=3.8' - kind: pypi name: decorator @@ -17788,34 +17714,6 @@ packages: - torch==2.2.2 - transformers editable: true -- kind: pypi - name: detect-and-track-objects - version: 0.1.0 - path: examples/python/detect_and_track_objects - sha256: 2c2d3d8b61d6a0bf44051fd7052e3087fd4762b9c434586078ea3d179940cba1 - requires_dist: - - numpy - - opencv-contrib-python>4.6 - - pillow - - requests>=2.31,<3 - - rerun-sdk - - timm==0.9.11 - - torch==2.2.2 - - transformers - editable: true -- kind: pypi - name: dicom-mri - version: 0.1.0 - path: examples/python/dicom_mri - sha256: 98cb91dc5758ae59e3cd0fb797f86f40fcf627f63e659365806f59feed4618d8 - requires_dist: - - dicom-numpy==0.6.2 - - numpy - - pydicom==2.3.0 - - requests>=2.31,<3 - - rerun-sdk - - types-requests>=2.31,<3 - editable: true - kind: pypi name: dicom-mri version: 0.1.0 @@ -17935,16 +17833,6 @@ packages: - rerun-sdk - scipy editable: true -- kind: pypi - name: dna - version: 0.1.0 - path: examples/python/dna - sha256: 15dd8b0ce0ee55262916ea9bc8fb93c72c2012cb01a78e6d24a526d92537eab4 - requires_dist: - - numpy - - rerun-sdk - - scipy - editable: true - kind: conda name: double-conversion version: 3.3.0 @@ -18079,18 +17967,6 @@ packages: - rerun-sdk - tqdm editable: true -- kind: pypi - name: drone-lidar - version: 0.1.0 - path: examples/python/drone_lidar - sha256: 4de8d4135d07f9b0389eeb8a3616a5a9941a868b4d876cc91d8b5351c3b8984d - requires_dist: - - laspy - - numpy - - requests - - rerun-sdk - - tqdm - editable: true - kind: conda name: exceptiongroup version: 1.2.2 @@ -18213,21 +18089,6 @@ packages: - tqdm requires_python: <3.12 editable: true -- kind: pypi - name: face-tracking - version: 0.1.0 - path: examples/python/face_tracking - sha256: b8725fe4d36c11aad2c6c936ba2b57c7f65a856aa179badca5d041db63119d55 - requires_dist: - - mediapipe==0.10.11 ; sys_platform != 'darwin' - - mediapipe==0.10.9 ; sys_platform == 'darwin' - - numpy - - opencv-python>4.6 - - requests - - rerun-sdk - - tqdm - requires_python: <3.12 - editable: true - kind: pypi name: fastjsonschema version: 2.20.0 @@ -18582,15 +18443,6 @@ packages: - six - termcolor - enum34 ; python_version < '3.4' -- kind: pypi - name: fire - version: 0.6.0 - url: https://files.pythonhosted.org/packages/1b/1b/84c63f592ecdfbb3d77d22a8d93c9b92791e4fa35677ad71a7d6449100f8/fire-0.6.0.tar.gz - sha256: 54ec5b996ecdd3c0309c800324a0703d6da512241bc73b553db959d98de0aa66 - requires_dist: - - six - - termcolor - - enum34 ; python_version < '3.4' - kind: pypi name: flatbuffers version: 24.3.25 @@ -18863,8 +18715,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/8b/6a/206391c869ab22d1374e2575cad7cab36b93b9e3d37f48f4696eed2c6e9e/fonttools-4.53.1-cp311-cp311-macosx_10_9_universal2.whl - sha256: da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1 + url: https://files.pythonhosted.org/packages/c8/e1/059700c154bd7170d1c37061239836d2e51ff608f47075450f06dd3c292a/fonttools-4.53.1-cp311-cp311-win_amd64.whl + sha256: d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18900,8 +18752,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/a4/22/0a0ad59d9367997fd74a00ad2e88d10559122e09f105e94d34c155aecc0a/fonttools-4.53.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3 + url: https://files.pythonhosted.org/packages/8b/6a/206391c869ab22d1374e2575cad7cab36b93b9e3d37f48f4696eed2c6e9e/fonttools-4.53.1-cp311-cp311-macosx_10_9_universal2.whl + sha256: da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18937,8 +18789,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/c8/e1/059700c154bd7170d1c37061239836d2e51ff608f47075450f06dd3c292a/fonttools-4.53.1-cp311-cp311-win_amd64.whl - sha256: d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02 + url: https://files.pythonhosted.org/packages/e1/67/fff766817e17d67208f8a1e72de15066149485acb5e4ff0816b11fd5fca3/fonttools-4.53.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18974,8 +18826,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/e1/67/fff766817e17d67208f8a1e72de15066149485acb5e4ff0816b11fd5fca3/fonttools-4.53.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719 + url: https://files.pythonhosted.org/packages/f5/7e/4060d88dbfaf446e1c9f0fe9cf13dba36ba47c4da85ce5c1df084ce47e7d/fonttools-4.53.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: 5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -19011,8 +18863,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/f5/7e/4060d88dbfaf446e1c9f0fe9cf13dba36ba47c4da85ce5c1df084ce47e7d/fonttools-4.53.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: 5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923 + url: https://files.pythonhosted.org/packages/a4/22/0a0ad59d9367997fd74a00ad2e88d10559122e09f105e94d34c155aecc0a/fonttools-4.53.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -19205,8 +19057,8 @@ packages: - kind: pypi name: freetype-py version: 2.4.0 - url: https://files.pythonhosted.org/packages/5f/34/76cfe866e482745ea8c9956b0be6198fd72d08d2be77b71596afdb8cd89f/freetype_py-2.4.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl - sha256: ce931f581d5038c4fea1f3d314254e0264e92441a5fdaef6817fe77b7bb888d3 + url: https://files.pythonhosted.org/packages/b4/f5/4b8bb492464247236bd3dabd7734b3ea49adc63cf2e53160e830ebccb39d/freetype_py-2.4.0-py3-none-win_amd64.whl + sha256: a2620788d4f0c00bd75fee2dfca61635ab0da856131598c96e2355d5257f70e5 requires_python: '>=3.7' - kind: pypi name: freetype-py @@ -19223,8 +19075,8 @@ packages: - kind: pypi name: freetype-py version: 2.4.0 - url: https://files.pythonhosted.org/packages/b4/f5/4b8bb492464247236bd3dabd7734b3ea49adc63cf2e53160e830ebccb39d/freetype_py-2.4.0-py3-none-win_amd64.whl - sha256: a2620788d4f0c00bd75fee2dfca61635ab0da856131598c96e2355d5257f70e5 + url: https://files.pythonhosted.org/packages/5f/34/76cfe866e482745ea8c9956b0be6198fd72d08d2be77b71596afdb8cd89f/freetype_py-2.4.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl + sha256: ce931f581d5038c4fea1f3d314254e0264e92441a5fdaef6817fe77b7bb888d3 requires_python: '>=3.7' - kind: conda name: fribidi @@ -19606,21 +19458,6 @@ packages: - tqdm requires_python: <3.12 editable: true -- kind: pypi - name: gesture-detection - version: 0.1.0 - path: examples/python/gesture_detection - sha256: 36dfc4cc822ee47f7aa29ba951bab8a94e96b9fd737daa324a441e6962a620bd - requires_dist: - - mediapipe==0.10.11 ; sys_platform != 'darwin' - - mediapipe==0.10.9 ; sys_platform == 'darwin' - - numpy - - opencv-python>4.9 - - requests>=2.31,<3 - - rerun-sdk - - tqdm - requires_python: <3.12 - editable: true - kind: conda name: gettext version: 0.22.5 @@ -20184,24 +20021,24 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -20216,8 +20053,8 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -20335,16 +20172,6 @@ packages: - multidict - protobuf>=3.20.0 ; extra == 'protobuf' requires_python: '>=3.7' -- kind: pypi - name: grpclib - version: 0.4.7 - url: https://files.pythonhosted.org/packages/79/b9/55936e462a5925190d7427e880b3033601d1effd13809b483d13a926061a/grpclib-0.4.7.tar.gz - sha256: 2988ef57c02b22b7a2e8e961792c41ccf97efc2ace91ae7a5b0de03c363823c3 - requires_dist: - - h2<5,>=3.1.0 - - multidict - - protobuf>=3.20.0 ; extra == 'protobuf' - requires_python: '>=3.7' - kind: conda name: gxx version: 12.4.0 @@ -21124,20 +20951,6 @@ packages: - rerun-sdk requires_python: <3.12 editable: true -- kind: pypi - name: human-pose-tracking - version: 0.1.0 - path: examples/python/human_pose_tracking - sha256: 8a80b67528d3f6d0c82671dc5c36cf551faa4b879f4434f0d386d8ef85666e86 - requires_dist: - - mediapipe==0.10.11 ; sys_platform != 'darwin' - - mediapipe==0.10.9 ; sys_platform == 'darwin' - - numpy - - opencv-python>4.6 - - requests>=2.31,<3 - - rerun-sdk - requires_python: <3.12 - editable: true - kind: pypi name: humanize version: 4.10.0 @@ -21551,15 +21364,6 @@ packages: - numpy - rerun-sdk editable: true -- kind: pypi - name: incremental-logging - version: 0.1.0 - path: examples/python/incremental_logging - sha256: c1efe33868c31fe5a07ab5f6e60d28f856735a9e0b221ff96abd2e711d60e894 - requires_dist: - - numpy - - rerun-sdk - editable: true - kind: conda name: iniconfig version: 2.0.0 @@ -21887,8 +21691,8 @@ packages: - kind: pypi name: jaxlib version: 0.4.30 - url: https://files.pythonhosted.org/packages/a6/a3/951da3d1487b2f8995a2a14cc7e9496c9a7c93aa1f1d0b33e833e24dee92/jaxlib-0.4.30-cp311-cp311-manylinux2014_x86_64.whl - sha256: 16b2ab18ea90d2e15941bcf45de37afc2f289a029129c88c8d7aba0404dd0043 + url: https://files.pythonhosted.org/packages/bb/1a/8f45ea28a5ca67e4d23ebd70fc78ea94be6fa20323f983c7607c32c6f9a5/jaxlib-0.4.30-cp311-cp311-win_amd64.whl + sha256: 3a2e2c11c179f8851a72249ba1ae40ae817dfaee9877d23b3b8f7c6b7a012f76 requires_dist: - scipy>=1.9 - numpy>=1.22 @@ -21898,8 +21702,8 @@ packages: - kind: pypi name: jaxlib version: 0.4.30 - url: https://files.pythonhosted.org/packages/bb/1a/8f45ea28a5ca67e4d23ebd70fc78ea94be6fa20323f983c7607c32c6f9a5/jaxlib-0.4.30-cp311-cp311-win_amd64.whl - sha256: 3a2e2c11c179f8851a72249ba1ae40ae817dfaee9877d23b3b8f7c6b7a012f76 + url: https://files.pythonhosted.org/packages/a6/a3/951da3d1487b2f8995a2a14cc7e9496c9a7c93aa1f1d0b33e833e24dee92/jaxlib-0.4.30-cp311-cp311-manylinux2014_x86_64.whl + sha256: 16b2ab18ea90d2e15941bcf45de37afc2f289a029129c88c8d7aba0404dd0043 requires_dist: - scipy>=1.9 - numpy>=1.22 @@ -22540,40 +22344,40 @@ packages: - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e + url: https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl + sha256: 6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl - sha256: 6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355 + url: https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797 + url: https://files.pythonhosted.org/packages/8d/26/b4569d1f29751fca22ee915b4ebfef5974f4ef239b3335fc072882bd62d9/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/8d/26/b4569d1f29751fca22ee915b4ebfef5974f4ef239b3335fc072882bd62d9/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437 + url: https://files.pythonhosted.org/packages/4a/fe/23d7fa78f7c66086d196406beb1fb2eaf629dd7adc01c3453033303d17fa/kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/a6/94/695922e71288855fc7cace3bdb52edda9d7e50edba77abb0c9d7abb51e96/kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90 + url: https://files.pythonhosted.org/packages/17/ba/17a706b232308e65f57deeccae503c268292e6a091313f6ce833a23093ea/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' @@ -22754,27 +22558,6 @@ packages: - pyproj ; extra == 'pyproj' - requests ; extra == 'requests' requires_python: '>=3.7' -- kind: pypi - name: laspy - version: 2.4.1 - url: https://files.pythonhosted.org/packages/7a/68/c864ea8e55c1fc3f1259375a0a31c60a06618cda4e14572c7d0e0aada6c2/laspy-2.4.1.tar.gz - sha256: 13caecc7325cb2242cb25394984d21b3b5f796c88bcb44bc2ed2d3cf1b972ac4 - requires_dist: - - numpy - - pytest ; extra == 'dev' - - coverage ; extra == 'dev' - - sphinx ; extra == 'dev' - - sphinx-rtd-theme ; extra == 'dev' - - nox ; extra == 'dev' - - black==22.3.0 ; extra == 'dev' - - pytest-benchmark ; extra == 'dev' - - m2r2 ; extra == 'dev' - - rangehttpserver ; extra == 'dev' - - laszip<0.3.0,>=0.2.1 ; extra == 'laszip' - - lazrs<0.6.0,>=0.5.0 ; extra == 'lazrs' - - pyproj ; extra == 'pyproj' - - requests ; extra == 'requests' - requires_python: '>=3.7' - kind: pypi name: lazy-loader version: '0.4' @@ -32145,27 +31928,6 @@ packages: - requests - rerun-sdk editable: true -- kind: pypi - name: lidar - version: 0.1.0 - path: examples/python/lidar - sha256: 10fe6d7b3a80959f913aada12c01bfecd6cd9854beaf6a8843a7ecd2215cd4bd - requires_dist: - - matplotlib - - numpy - - nuscenes-devkit - - requests - - rerun-sdk - editable: true -- kind: pypi - name: live-camera-edge-detection - version: 0.1.0 - path: examples/python/live_camera_edge_detection - sha256: f1edef43efce87f55726e3b5d6a2f813667968f8e8185873a74b9dc61c0f040f - requires_dist: - - opencv-python - - rerun-sdk - editable: true - kind: pypi name: live-camera-edge-detection version: 0.1.0 @@ -32184,27 +31946,6 @@ packages: - numpy - rerun-sdk editable: true -- kind: pypi - name: live-scrolling-plot - version: 0.1.0 - path: examples/python/live_scrolling_plot - sha256: 1debab1814169399bb2ed23af2cd97a4693e7a4d4ee55e74bcb8804bf421e8fc - requires_dist: - - numpy - - rerun-sdk - editable: true -- kind: pypi - name: llm-embedding-ner - version: 0.1.0 - path: examples/python/llm_embedding_ner - sha256: 6f5925cbe333d529421ef9a5114f85317bdd8b4200c1e9ff6798dff5e3a7f16f - requires_dist: - - rerun-sdk - - torch - - transformers - - umap-learn - requires_python: <3.12 - editable: true - kind: pypi name: llm-embedding-ner version: 0.1.0 @@ -32308,26 +32049,26 @@ packages: - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/2f/b2/4429433eb2dc8379e2cb582502dca074c23837f8fd009907f78a24de4c25/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2 + url: https://files.pythonhosted.org/packages/95/8c/de3276d773ab6ce3ad676df5fab5aac19696b2956319d65d7dd88fb10f19/llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/6b/99/5d00a7d671b1ba1751fc9f19d3b36f3300774c6eebe2bcdb5f6191763eb4/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749 + url: https://files.pythonhosted.org/packages/2f/b2/4429433eb2dc8379e2cb582502dca074c23837f8fd009907f78a24de4c25/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/95/8c/de3276d773ab6ce3ad676df5fab5aac19696b2956319d65d7dd88fb10f19/llvmlite-0.43.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 3e8d0618cb9bfe40ac38a9633f2493d4d4e9fcc2f438d39a4e854f39cc0f5f98 + url: https://files.pythonhosted.org/packages/ee/e1/38deed89ced4cf378c61e232265cfe933ccde56ae83c901aa68b477d14b1/llvmlite-0.43.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: e0a9a1a39d4bf3517f2af9d23d479b4175ead205c592ceeb8b89af48a327ea57 requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/ee/e1/38deed89ced4cf378c61e232265cfe933ccde56ae83c901aa68b477d14b1/llvmlite-0.43.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: e0a9a1a39d4bf3517f2af9d23d479b4175ead205c592ceeb8b89af48a327ea57 + url: https://files.pythonhosted.org/packages/6b/99/5d00a7d671b1ba1751fc9f19d3b36f3300774c6eebe2bcdb5f6191763eb4/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749 requires_python: '>=3.9' - kind: pypi name: log-file @@ -32337,14 +32078,6 @@ packages: requires_dist: - rerun-sdk editable: true -- kind: pypi - name: log-file - version: 0.1.0 - path: examples/python/log_file - sha256: fb6af8faeaac3e8d16da4ab40e26a73dd0e63483f34aa36298c32f7e39324fd3 - requires_dist: - - rerun-sdk - editable: true - kind: pypi name: lxml version: 5.2.2 @@ -32384,8 +32117,8 @@ packages: - kind: pypi name: lxml version: 5.2.2 - url: https://files.pythonhosted.org/packages/ad/b7/0dc82afed00c4c189cfd0b83464f9a431c66de8e73d911063956a147276a/lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5 + url: https://files.pythonhosted.org/packages/da/6a/24e9f77d17668dd4ac0a6c2a56113fd3e0db07cee51e3a67afcd47c597e5/lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl + sha256: 45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -32396,8 +32129,8 @@ packages: - kind: pypi name: lxml version: 5.2.2 - url: https://files.pythonhosted.org/packages/da/6a/24e9f77d17668dd4ac0a6c2a56113fd3e0db07cee51e3a67afcd47c597e5/lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl - sha256: 45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545 + url: https://files.pythonhosted.org/packages/ad/b7/0dc82afed00c4c189cfd0b83464f9a431c66de8e73d911063956a147276a/lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -32601,14 +32334,14 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f + url: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced + url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl + sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 requires_python: '>=3.7' - kind: pypi name: markupsafe @@ -32619,14 +32352,14 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 + url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl - sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 + url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 requires_python: '>=3.7' - kind: conda name: markupsafe @@ -32751,30 +32484,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/0a/d4/c0812c410de88e8646727a7c000741331875ae556018725ae169d206f0a2/matplotlib-3.9.1.post1-cp311-cp311-win_amd64.whl - sha256: c44edab5b849e0fc1f1c9d6e13eaa35ef65925f7be45be891d9784709ad95561 - requires_dist: - - contourpy>=1.0.1 - - cycler>=0.10 - - fonttools>=4.22.0 - - kiwisolver>=1.3.1 - - numpy>=1.23 - - packaging>=20.0 - - pillow>=8 - - pyparsing>=2.3.1 - - python-dateutil>=2.7 - - importlib-resources>=3.2.0 ; python_version < '3.10' - - meson-python>=0.13.1 ; extra == 'dev' - - numpy>=1.25 ; extra == 'dev' - - pybind11>=2.6 ; extra == 'dev' - - setuptools-scm>=7 ; extra == 'dev' - - setuptools>=64 ; extra == 'dev' - requires_python: '>=3.9' -- kind: pypi - name: matplotlib - version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/41/dc/1f51d34daebbfe172b78fa5b5be467554b973ef30b80ed2f6200b34d3223/matplotlib-3.9.1.post1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: b08b46058fe2a31ecb81ef6aa3611f41d871f6a8280e9057cb4016cb3d8e894a + url: https://files.pythonhosted.org/packages/c3/2b/1c9e695967edb54f0cfb1ea5d41f5482344cf245489f8a47aa427825f264/matplotlib-3.9.1.post1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 4b49fee26d64aefa9f061b575f0f7b5fc4663e51f87375c7239efa3d30d908fa requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32795,8 +32506,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/43/ef/3fadf6545a0c609c7720477b2bfa2e578f99c106e3bd1aaf591e006c3434/matplotlib-3.9.1.post1-cp311-cp311-macosx_11_0_arm64.whl - sha256: 22b344e84fcc574f561b5731f89a7625db8ef80cdbb0026a8ea855a33e3429d1 + url: https://files.pythonhosted.org/packages/0a/d4/c0812c410de88e8646727a7c000741331875ae556018725ae169d206f0a2/matplotlib-3.9.1.post1-cp311-cp311-win_amd64.whl + sha256: c44edab5b849e0fc1f1c9d6e13eaa35ef65925f7be45be891d9784709ad95561 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32817,8 +32528,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/a5/8b/90fae9c1b34ef3252003c26b15e8cb26b83701e34e5acf6430919c2c5c89/matplotlib-3.9.1.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 89eb7e89e2b57856533c5c98f018aa3254fa3789fcd86d5f80077b9034a54c9a + url: https://files.pythonhosted.org/packages/41/dc/1f51d34daebbfe172b78fa5b5be467554b973ef30b80ed2f6200b34d3223/matplotlib-3.9.1.post1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: b08b46058fe2a31ecb81ef6aa3611f41d871f6a8280e9057cb4016cb3d8e894a requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32839,8 +32550,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/c3/2b/1c9e695967edb54f0cfb1ea5d41f5482344cf245489f8a47aa427825f264/matplotlib-3.9.1.post1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 4b49fee26d64aefa9f061b575f0f7b5fc4663e51f87375c7239efa3d30d908fa + url: https://files.pythonhosted.org/packages/43/ef/3fadf6545a0c609c7720477b2bfa2e578f99c106e3bd1aaf591e006c3434/matplotlib-3.9.1.post1-cp311-cp311-macosx_11_0_arm64.whl + sha256: 22b344e84fcc574f561b5731f89a7625db8ef80cdbb0026a8ea855a33e3429d1 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32860,9 +32571,9 @@ packages: requires_python: '>=3.9' - kind: pypi name: matplotlib - version: 3.9.2 - url: https://files.pythonhosted.org/packages/01/75/6c7ce560e95714a10fcbb3367d1304975a1a3e620f72af28921b796403f3/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447 + version: 3.9.1.post1 + url: https://files.pythonhosted.org/packages/a5/8b/90fae9c1b34ef3252003c26b15e8cb26b83701e34e5acf6430919c2c5c89/matplotlib-3.9.1.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 89eb7e89e2b57856533c5c98f018aa3254fa3789fcd86d5f80077b9034a54c9a requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32883,8 +32594,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/28/ba/8be09886eb56ac04a218a1dc3fa728a5c4cac60b019b4f1687885166da00/matplotlib-3.9.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41 + url: https://files.pythonhosted.org/packages/8b/ce/15b0bb2fb29b3d46211d8ca740b96b5232499fc49200b58b8d571292c9a6/matplotlib-3.9.2-cp311-cp311-win_amd64.whl + sha256: ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32927,8 +32638,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/8b/ce/15b0bb2fb29b3d46211d8ca740b96b5232499fc49200b58b8d571292c9a6/matplotlib-3.9.2-cp311-cp311-win_amd64.whl - sha256: ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7 + url: https://files.pythonhosted.org/packages/e6/9a/5991972a560db3ab621312a7ca5efec339ae2122f25901c0846865c4b72f/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32949,8 +32660,30 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/e6/9a/5991972a560db3ab621312a7ca5efec339ae2122f25901c0846865c4b72f/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f + url: https://files.pythonhosted.org/packages/28/ba/8be09886eb56ac04a218a1dc3fa728a5c4cac60b019b4f1687885166da00/matplotlib-3.9.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41 + requires_dist: + - contourpy>=1.0.1 + - cycler>=0.10 + - fonttools>=4.22.0 + - kiwisolver>=1.3.1 + - numpy>=1.23 + - packaging>=20.0 + - pillow>=8 + - pyparsing>=2.3.1 + - python-dateutil>=2.7 + - importlib-resources>=3.2.0 ; python_version < '3.10' + - meson-python>=0.13.1 ; extra == 'dev' + - numpy>=1.25 ; extra == 'dev' + - pybind11>=2.6 ; extra == 'dev' + - setuptools-scm>=7 ; extra == 'dev' + - setuptools>=64 ; extra == 'dev' + requires_python: '>=3.9' +- kind: pypi + name: matplotlib + version: 3.9.2 + url: https://files.pythonhosted.org/packages/01/75/6c7ce560e95714a10fcbb3367d1304975a1a3e620f72af28921b796403f3/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -33088,8 +32821,8 @@ packages: - kind: pypi name: mediapipe version: 0.10.9 - url: https://files.pythonhosted.org/packages/a3/3a/f309c6bdebe596cc8c960542e167331cb01ef130ec38f3da46a499718889/mediapipe-0.10.9-cp311-cp311-macosx_11_0_universal2.whl - sha256: 8733735f582e6e6a05bf9b15c48b03a6387a0795793a2530aa1189eecfd33780 + url: https://files.pythonhosted.org/packages/c1/71/38b16b1e4504ff92dff875d455c19e62125fccd73d5ce7e06b560f77fd26/mediapipe-0.10.9-cp311-cp311-macosx_11_0_x86_64.whl + sha256: b7dde54b82732479b9b856c9230b9f7b3da55b0913dde5254a7489e20c2e3c6e requires_dist: - absl-py - attrs>=19.1.0 @@ -33102,8 +32835,8 @@ packages: - kind: pypi name: mediapipe version: 0.10.9 - url: https://files.pythonhosted.org/packages/c1/71/38b16b1e4504ff92dff875d455c19e62125fccd73d5ce7e06b560f77fd26/mediapipe-0.10.9-cp311-cp311-macosx_11_0_x86_64.whl - sha256: b7dde54b82732479b9b856c9230b9f7b3da55b0913dde5254a7489e20c2e3c6e + url: https://files.pythonhosted.org/packages/a3/3a/f309c6bdebe596cc8c960542e167331cb01ef130ec38f3da46a499718889/mediapipe-0.10.9-cp311-cp311-macosx_11_0_universal2.whl + sha256: 8733735f582e6e6a05bf9b15c48b03a6387a0795793a2530aa1189eecfd33780 requires_dist: - absl-py - attrs>=19.1.0 @@ -33183,16 +32916,6 @@ packages: - scikit-image - scikit-learn requires_python: '>=3.5' -- kind: pypi - name: mesh-to-sdf - version: 0.0.15 - url: git+https://github.com/marian42/mesh_to_sdf.git@c9f26e6399f7fd8deb40c7fba02c7e74aca6c657 - requires_dist: - - pyopengl - - pyrender - - scikit-image - - scikit-learn - requires_python: '>=3.5' - kind: pypi name: minimal version: 0.1.0 @@ -33202,24 +32925,6 @@ packages: - numpy - rerun-sdk editable: true -- kind: pypi - name: minimal - version: 0.1.0 - path: examples/python/minimal - sha256: 871c1ec39ceb3af42679653369402d66672d4bb9850a727b27db05c16653c8dd - requires_dist: - - numpy - - rerun-sdk - editable: true -- kind: pypi - name: minimal-options - version: 0.1.0 - path: examples/python/minimal_options - sha256: 84d5a8787772da382454f2f3b44d54027a606bff043872dab559cc4604ac82f0 - requires_dist: - - numpy - - rerun-sdk - editable: true - kind: pypi name: minimal-options version: 0.1.0 @@ -33272,8 +32977,8 @@ packages: - kind: pypi name: ml-dtypes version: 0.4.0 - url: https://files.pythonhosted.org/packages/84/17/a936d3dfad84d028ba8539a93167274b7dcd7985e0d9df487e94a62f9428/ml_dtypes-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: e1e2f4237b459a63c97c2c9f449baa637d7e4c20addff6a9bac486f22432f3b6 + url: https://files.pythonhosted.org/packages/f0/36/290745178e5776f7416818abc1334c1b19afb93c7c87fd1bef3cc99f84ca/ml_dtypes-0.4.0-cp311-cp311-win_amd64.whl + sha256: 75b4faf99d0711b81f393db36d210b4255fd419f6f790bc6c1b461f95ffb7a9e requires_dist: - numpy>1.20 - numpy>=1.21.2 ; python_version >= '3.10' @@ -33288,8 +32993,8 @@ packages: - kind: pypi name: ml-dtypes version: 0.4.0 - url: https://files.pythonhosted.org/packages/f0/36/290745178e5776f7416818abc1334c1b19afb93c7c87fd1bef3cc99f84ca/ml_dtypes-0.4.0-cp311-cp311-win_amd64.whl - sha256: 75b4faf99d0711b81f393db36d210b4255fd419f6f790bc6c1b461f95ffb7a9e + url: https://files.pythonhosted.org/packages/84/17/a936d3dfad84d028ba8539a93167274b7dcd7985e0d9df487e94a62f9428/ml_dtypes-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e1e2f4237b459a63c97c2c9f449baa637d7e4c20addff6a9bac486f22432f3b6 requires_dist: - numpy>1.20 - numpy>=1.21.2 ; python_version >= '3.10' @@ -33336,32 +33041,32 @@ packages: - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: 612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd + url: https://files.pythonhosted.org/packages/3f/e1/7fdd0f39565df3af87d6c2903fb66a7d529fbd0a8a066045d7a5b6ad1145/multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3 requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e + url: https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl + sha256: 2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/3f/e1/7fdd0f39565df3af87d6c2903fb66a7d529fbd0a8a066045d7a5b6ad1145/multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3 + url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed + url: https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: 612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl - sha256: 2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea + url: https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed requires_python: '>=3.7' - kind: conda name: multidict @@ -33463,14 +33168,6 @@ packages: requires_dist: - rerun-sdk editable: true -- kind: pypi - name: multiprocess-logging - version: 0.1.0 - path: examples/python/multiprocess_logging - sha256: 90ae836d45110662ac53e73a092a5298ab67d89873eed81d1773dba601a62eb2 - requires_dist: - - rerun-sdk - editable: true - kind: pypi name: multitasking version: 0.0.11 @@ -33485,15 +33182,6 @@ packages: - numpy - rerun-sdk editable: true -- kind: pypi - name: multithreading - version: 0.1.0 - path: examples/python/multithreading - sha256: 85b43cb06183386edd0a8820c0c9eb50398c197fd0da8ba5050f2cf2b24bc23e - requires_dist: - - numpy - - rerun-sdk - editable: true - kind: conda name: mypy version: 1.8.0 @@ -34350,8 +34038,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/57/03/2b4245b05b71c0cee667e6a0b51606dfa7f4157c9093d71c6b208385a611/numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - sha256: 4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8 + url: https://files.pythonhosted.org/packages/79/89/2d924ca60dbf949f18a6fec223a2445f5f428d9a5f97a6b29c2122319015/numba-0.60.0-cp311-cp311-win_amd64.whl + sha256: cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34359,8 +34047,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/79/89/2d924ca60dbf949f18a6fec223a2445f5f428d9a5f97a6b29c2122319015/numba-0.60.0-cp311-cp311-win_amd64.whl - sha256: cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2 + url: https://files.pythonhosted.org/packages/98/ad/df18d492a8f00d29a30db307904b9b296e37507034eedb523876f3a2e13e/numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34368,8 +34056,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/98/ad/df18d492a8f00d29a30db307904b9b296e37507034eedb523876f3a2e13e/numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8 + url: https://files.pythonhosted.org/packages/f9/4c/8889ac94c0b33dca80bed11564b8c6d9ea14d7f094e674c58e5c5b05859b/numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl + sha256: 5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34386,8 +34074,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/f9/4c/8889ac94c0b33dca80bed11564b8c6d9ea14d7f094e674c58e5c5b05859b/numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl - sha256: 5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703 + url: https://files.pythonhosted.org/packages/57/03/2b4245b05b71c0cee667e6a0b51606dfa7f4157c9093d71c6b208385a611/numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + sha256: 4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34525,18 +34213,6 @@ packages: - requests - rerun-sdk editable: true -- kind: pypi - name: nuscenes-dataset - version: 0.1.0 - path: examples/python/nuscenes_dataset - sha256: 78903b7670fac2b4c27637efc9aa6f63b7b70502ce3d5f88e4353aef5607cf40 - requires_dist: - - matplotlib - - numpy - - nuscenes-devkit - - requests - - rerun-sdk - editable: true - kind: pypi name: nuscenes-devkit version: 1.1.9 @@ -34568,16 +34244,6 @@ packages: - opencv-python - numpy editable: true -- kind: pypi - name: nv12 - version: 0.1.0 - path: examples/python/nv12 - sha256: c8ca97c5d8c04037cd5eb9a65be7b1e7d667c11d4dba3ee9aad5956ccf926dc4 - requires_dist: - - rerun-sdk>=0.10 - - opencv-python - - numpy - editable: true - kind: pypi name: nvidia-cublas-cu12 version: 12.1.3.1 @@ -34671,19 +34337,6 @@ packages: - rerun-sdk - scipy editable: true -- kind: pypi - name: objectron - version: 0.1.0 - path: examples/python/objectron - sha256: b2be2b675353b4238e7778b1cef8351950832c32b5e5c34415601c030a421a27 - requires_dist: - - betterproto[compiler] - - numpy - - opencv-python>4.6 - - requests>=2.31,<3 - - rerun-sdk - - scipy - editable: true - kind: conda name: ocl-icd version: 2.3.2 @@ -34714,20 +34367,6 @@ packages: - tqdm requires_python: '>=3.10' editable: true -- kind: pypi - name: open-photogrammetry-format - version: 0.1.0 - path: examples/python/open_photogrammetry_format - sha256: 1bf1ac24e064bb75c7f5672b761e519b8b941354a6d9c44d824643ff64f15e80 - requires_dist: - - numpy - - pillow - - pyopf - - requests - - rerun-sdk - - tqdm - requires_python: '>=3.10' - editable: true - kind: conda name: opencv version: 4.10.0 @@ -34827,8 +34466,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/09/94/d077c4c976c2d7a88812fd55396e92edae0e0c708689dbd8c8f508920e47/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl - sha256: dea80d4db73b8acccf9e16b5744bf3654f47b22745074263f0a6c10de26c5ef5 + url: https://files.pythonhosted.org/packages/a7/9e/7110d2c5d543ab03b9581dbb1f8e2429863e44e0c9b4960b766f230c1279/opencv_contrib_python-4.10.0.84-cp37-abi3-win_amd64.whl + sha256: 47ec3160dae75f70e099b286d1a2e086d20dac8b06e759f60eaf867e6bdecba7 requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -34844,8 +34483,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/92/64/c1194510eaed272d86b53a08c790ca6ed1c450f06d401c49c8145fc46d40/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_11_0_arm64.whl - sha256: ee4b0919026d8c533aeb69b16c6ec4a891a2f6844efaa14121bf68838753209c + url: https://files.pythonhosted.org/packages/09/94/d077c4c976c2d7a88812fd55396e92edae0e0c708689dbd8c8f508920e47/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl + sha256: dea80d4db73b8acccf9e16b5744bf3654f47b22745074263f0a6c10de26c5ef5 requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -34861,8 +34500,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/a7/9e/7110d2c5d543ab03b9581dbb1f8e2429863e44e0c9b4960b766f230c1279/opencv_contrib_python-4.10.0.84-cp37-abi3-win_amd64.whl - sha256: 47ec3160dae75f70e099b286d1a2e086d20dac8b06e759f60eaf867e6bdecba7 + url: https://files.pythonhosted.org/packages/f8/76/f76fe74b864f3cfa737173ca12e8890aad8369e980006fb8a0b6cd14c6c7/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 040575b69e4f3aa761676bace4e3d1b8485fbfaf77ef77b266ab6bda5a3b5e9b requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -34878,8 +34517,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/b0/e0/8f5d065ebb2e5941d289c5f653f944318f9e418bc5167bc6a346ab5e0f6a/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a261223db41f6e512d76deaf21c8fcfb4fbbcbc2de62ca7f74a05f2c9ee489ef + url: https://files.pythonhosted.org/packages/92/64/c1194510eaed272d86b53a08c790ca6ed1c450f06d401c49c8145fc46d40/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_11_0_arm64.whl + sha256: ee4b0919026d8c533aeb69b16c6ec4a891a2f6844efaa14121bf68838753209c requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -34895,8 +34534,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/f8/76/f76fe74b864f3cfa737173ca12e8890aad8369e980006fb8a0b6cd14c6c7/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 040575b69e4f3aa761676bace4e3d1b8485fbfaf77ef77b266ab6bda5a3b5e9b + url: https://files.pythonhosted.org/packages/b0/e0/8f5d065ebb2e5941d289c5f653f944318f9e418bc5167bc6a346ab5e0f6a/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a261223db41f6e512d76deaf21c8fcfb4fbbcbc2de62ca7f74a05f2c9ee489ef requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -35411,8 +35050,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 + url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl + sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -35687,8 +35326,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl - sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 + url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -36046,8 +35685,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36070,8 +35709,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36094,8 +35733,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36118,8 +35757,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36142,8 +35781,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36166,8 +35805,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c + url: https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36193,8 +35832,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe + url: https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl + sha256: cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36220,8 +35859,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: 76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319 + url: https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36247,8 +35886,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl - sha256: cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91 + url: https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36274,8 +35913,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be + url: https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: 76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36422,15 +36061,6 @@ packages: - numpy - rerun-sdk editable: true -- kind: pypi - name: plots - version: 0.1.0 - path: examples/python/plots - sha256: 398c85932db816f766e2d703568060efe4520a6e734f91d69387bbdd143b3f97 - requires_dist: - - numpy - - rerun-sdk - editable: true - kind: conda name: pluggy version: 1.5.0 @@ -36566,14 +36196,14 @@ packages: - kind: pypi name: protobuf version: 5.27.2 - url: https://files.pythonhosted.org/packages/27/e4/8dc4546be46873f8950cb44cdfe19b79d66d26e53c4ee5e3440406257fcd/protobuf-5.27.2-cp38-abi3-manylinux2014_x86_64.whl - sha256: b848dbe1d57ed7c191dfc4ea64b8b004a3f9ece4bf4d0d80a367b76df20bf36e + url: https://files.pythonhosted.org/packages/75/44/6ae304790fad936bb4cf09907a05d669b7600458a02b6c960fdaaeeab06e/protobuf-5.27.2-cp38-abi3-macosx_10_9_universal2.whl + sha256: a109916aaac42bff84702fb5187f3edadbc7c97fc2c99c5ff81dd15dcce0d1e5 requires_python: '>=3.8' - kind: pypi name: protobuf version: 5.27.2 - url: https://files.pythonhosted.org/packages/75/44/6ae304790fad936bb4cf09907a05d669b7600458a02b6c960fdaaeeab06e/protobuf-5.27.2-cp38-abi3-macosx_10_9_universal2.whl - sha256: a109916aaac42bff84702fb5187f3edadbc7c97fc2c99c5ff81dd15dcce0d1e5 + url: https://files.pythonhosted.org/packages/cd/c7/a534268f9c3780be1ba50f5ed96243fa9cf6224a445de662c34e91ce0e61/protobuf-5.27.2-cp38-abi3-manylinux2014_aarch64.whl + sha256: 176c12b1f1c880bf7a76d9f7c75822b6a2bc3db2d28baa4d300e8ce4cde7409b requires_python: '>=3.8' - kind: pypi name: protobuf @@ -36584,14 +36214,14 @@ packages: - kind: pypi name: protobuf version: 5.27.2 - url: https://files.pythonhosted.org/packages/cd/c7/a534268f9c3780be1ba50f5ed96243fa9cf6224a445de662c34e91ce0e61/protobuf-5.27.2-cp38-abi3-manylinux2014_aarch64.whl - sha256: 176c12b1f1c880bf7a76d9f7c75822b6a2bc3db2d28baa4d300e8ce4cde7409b + url: https://files.pythonhosted.org/packages/27/e4/8dc4546be46873f8950cb44cdfe19b79d66d26e53c4ee5e3440406257fcd/protobuf-5.27.2-cp38-abi3-manylinux2014_x86_64.whl + sha256: b848dbe1d57ed7c191dfc4ea64b8b004a3f9ece4bf4d0d80a367b76df20bf36e requires_python: '>=3.8' - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl - sha256: c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0 + url: https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -36602,8 +36232,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd + url: https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl + sha256: 33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -36614,8 +36244,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl - sha256: 33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3 + url: https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl + sha256: c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -36638,8 +36268,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132 + url: https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -37118,8 +36748,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/30/d1/63a7c248432c71c7d3ee803e706590a0b81ce1a8d2b2ae49677774b813bb/pyarrow-17.0.0-cp311-cp311-win_amd64.whl - sha256: a27532c38f3de9eb3e90ecab63dfda948a8ca859a66e3a47f5f42d1e403c4d03 + url: https://files.pythonhosted.org/packages/f9/46/ce89f87c2936f5bb9d879473b9663ce7a4b1f4359acc2f0eb39865eaa1af/pyarrow-17.0.0-cp311-cp311-macosx_10_15_x86_64.whl + sha256: 1c8856e2ef09eb87ecf937104aacfa0708f22dfeb039c363ec99735190ffb977 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -37131,8 +36761,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/4c/21/9ca93b84b92ef927814cb7ba37f0774a484c849d58f0b692b16af8eebcfb/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: e3343cb1e88bc2ea605986d4b94948716edc7a8d14afd4e2c097232f729758b4 + url: https://files.pythonhosted.org/packages/8d/8e/ce2e9b2146de422f6638333c01903140e9ada244a2a477918a368306c64c/pyarrow-17.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 2e19f569567efcbbd42084e87f948778eb371d308e137a0f97afe19bb860ccb3 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -37144,8 +36774,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/8d/8e/ce2e9b2146de422f6638333c01903140e9ada244a2a477918a368306c64c/pyarrow-17.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 2e19f569567efcbbd42084e87f948778eb371d308e137a0f97afe19bb860ccb3 + url: https://files.pythonhosted.org/packages/30/d1/63a7c248432c71c7d3ee803e706590a0b81ce1a8d2b2ae49677774b813bb/pyarrow-17.0.0-cp311-cp311-win_amd64.whl + sha256: a27532c38f3de9eb3e90ecab63dfda948a8ca859a66e3a47f5f42d1e403c4d03 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -37157,8 +36787,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/d8/81/69b6606093363f55a2a574c018901c40952d4e902e670656d18213c71ad7/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: dc5c31c37409dfbc5d014047817cb4ccd8c1ea25d19576acf1a001fe07f5b420 + url: https://files.pythonhosted.org/packages/4c/21/9ca93b84b92ef927814cb7ba37f0774a484c849d58f0b692b16af8eebcfb/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: e3343cb1e88bc2ea605986d4b94948716edc7a8d14afd4e2c097232f729758b4 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -37170,8 +36800,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/f9/46/ce89f87c2936f5bb9d879473b9663ce7a4b1f4359acc2f0eb39865eaa1af/pyarrow-17.0.0-cp311-cp311-macosx_10_15_x86_64.whl - sha256: 1c8856e2ef09eb87ecf937104aacfa0708f22dfeb039c363ec99735190ffb977 + url: https://files.pythonhosted.org/packages/d8/81/69b6606093363f55a2a574c018901c40952d4e902e670656d18213c71ad7/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: dc5c31c37409dfbc5d014047817cb4ccd8c1ea25d19576acf1a001fe07f5b420 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -37553,8 +37183,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/8b/d4/7279d072c0255d07c541326f6058effb1b08190f49695bf2c22aae666878/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 5968a1e5421719af9eb7ccee4c540bfb18b1fc95d30d9a48571d0aaeb159a1ae + url: https://files.pythonhosted.org/packages/d5/9c/09cd808743338db170915deb35fa020b792d583238afe55f27c011f91c3c/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6a07f57f991e379959c0f4a1b9ea35d875876433b7f45c6d8fe6b718e58834bc requires_dist: - matplotlib>=2.1.0 - numpy @@ -37562,8 +37192,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/d5/9c/09cd808743338db170915deb35fa020b792d583238afe55f27c011f91c3c/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6a07f57f991e379959c0f4a1b9ea35d875876433b7f45c6d8fe6b718e58834bc + url: https://files.pythonhosted.org/packages/8b/d4/7279d072c0255d07c541326f6058effb1b08190f49695bf2c22aae666878/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 5968a1e5421719af9eb7ccee4c540bfb18b1fc95d30d9a48571d0aaeb159a1ae requires_dist: - matplotlib>=2.1.0 - numpy @@ -37617,16 +37247,6 @@ packages: - deprecated - dataclasses ; python_version >= '3.6' and python_version < '3.7' requires_python: '>=3.6' -- kind: pypi - name: pygltflib - version: 1.16.2 - url: https://files.pythonhosted.org/packages/38/d7/0b8e35cb3ff69dd981e358e72e0a5632f847d4bd61876be04518cb4e075a/pygltflib-1.16.2.tar.gz - sha256: 4f9481f5841b0b8fb7b271b0414b394b503405260a6ee0cf2c330a5420d19b64 - requires_dist: - - dataclasses-json>=0.0.25 - - deprecated - - dataclasses ; python_version >= '3.6' and python_version < '3.7' - requires_python: '>=3.6' - kind: pypi name: pygments version: 2.18.0 @@ -37659,8 +37279,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 + url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl + sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 requires_dist: - cffi>=1.4.1 - sphinx>=1.6.5 ; extra == 'docs' @@ -37671,8 +37291,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 + url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 requires_dist: - cffi>=1.4.1 - sphinx>=1.6.5 ; extra == 'docs' @@ -37683,8 +37303,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/75/0b8ede18506041c0bf23ac4d8e2971b4161cd6ce630b177d0a08eb0d8857/PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl - sha256: 401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 + url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl + sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 requires_dist: - cffi>=1.4.1 - sphinx>=1.6.5 ; extra == 'docs' @@ -37750,8 +37370,8 @@ packages: - kind: pypi name: pyproj version: 3.6.0 - url: https://files.pythonhosted.org/packages/1a/07/2f1975c98c840eb4fa54fb95c3070c4255bdf41fd6866e05cffff41b4f4e/pyproj-3.6.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: ba5e7c8ddd6ed5a3f9fcf95ea80ba44c931913723de2ece841c94bb38b200c4a + url: https://files.pythonhosted.org/packages/c8/5a/215a1894e50167d91b471d8fc413ca30034c48e5d3dfac78d12df4c840d5/pyproj-3.6.0-cp311-cp311-win_amd64.whl + sha256: 8fbac2eb9a0e425d7d6b7c6f4ebacd675cf3bdef0c59887057b8b4b0374e7c12 requires_dist: - certifi requires_python: '>=3.9' @@ -37766,24 +37386,24 @@ packages: - kind: pypi name: pyproj version: 3.6.0 - url: https://files.pythonhosted.org/packages/81/eb/3e31e15fdee9d54bdbc575b6384bd7e54f63590fcb4d5c247ad38a81eb44/pyproj-3.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: dfe392dfc0eba2248dc08c976a72f52ff9da2bddfddfd9ff5dcf18e8e88200c7 + url: https://files.pythonhosted.org/packages/82/ea/208144cd3fb42a3bf70630a1300c32a9dc1705b777d6c2fb1ebd1517fad5/pyproj-3.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 08dfc5c9533c78a97afae9d53b99b810a4a8f97c3be9eb2b8f323b726c736403 requires_dist: - certifi requires_python: '>=3.9' - kind: pypi name: pyproj version: 3.6.0 - url: https://files.pythonhosted.org/packages/82/ea/208144cd3fb42a3bf70630a1300c32a9dc1705b777d6c2fb1ebd1517fad5/pyproj-3.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 08dfc5c9533c78a97afae9d53b99b810a4a8f97c3be9eb2b8f323b726c736403 + url: https://files.pythonhosted.org/packages/1a/07/2f1975c98c840eb4fa54fb95c3070c4255bdf41fd6866e05cffff41b4f4e/pyproj-3.6.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: ba5e7c8ddd6ed5a3f9fcf95ea80ba44c931913723de2ece841c94bb38b200c4a requires_dist: - certifi requires_python: '>=3.9' - kind: pypi name: pyproj version: 3.6.0 - url: https://files.pythonhosted.org/packages/c8/5a/215a1894e50167d91b471d8fc413ca30034c48e5d3dfac78d12df4c840d5/pyproj-3.6.0-cp311-cp311-win_amd64.whl - sha256: 8fbac2eb9a0e425d7d6b7c6f4ebacd675cf3bdef0c59887057b8b4b0374e7c12 + url: https://files.pythonhosted.org/packages/81/eb/3e31e15fdee9d54bdbc575b6384bd7e54f63590fcb4d5c247ad38a81eb44/pyproj-3.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: dfe392dfc0eba2248dc08c976a72f52ff9da2bddfddfd9ff5dcf18e8e88200c7 requires_dist: - certifi requires_python: '>=3.9' @@ -38151,32 +37771,32 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab + url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl + sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d + url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 + url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl - sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 + url: https://files.pythonhosted.org/packages/28/09/55f715ddbf95a054b764b547f617e22f1d5e45d83905660e9a088078fe67/PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/ec/0d/26fb23e8863e0aeaac0c64e03fd27367ad2ae3f3cccf3798ee98ce160368/PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 + url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 requires_python: '>=3.6' - kind: pypi name: pyzmq @@ -38197,16 +37817,16 @@ packages: - kind: pypi name: pyzmq version: 26.0.3 - url: https://files.pythonhosted.org/packages/9b/20/92275f936eaa612f0192f8a02b2f66564e41498216f37a760501d2591149/pyzmq-26.0.3-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a + url: https://files.pythonhosted.org/packages/e5/b5/625e45790a1b091f54d5d47fd267d051cabdec4f01144f6b2fcb7306515b/pyzmq-26.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7 requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' - kind: pypi name: pyzmq version: 26.0.3 - url: https://files.pythonhosted.org/packages/e5/b5/625e45790a1b091f54d5d47fd267d051cabdec4f01144f6b2fcb7306515b/pyzmq-26.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7 + url: https://files.pythonhosted.org/packages/9b/20/92275f936eaa612f0192f8a02b2f66564e41498216f37a760501d2591149/pyzmq-26.0.3-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' @@ -38441,17 +38061,6 @@ packages: - rerun-sdk - trimesh==3.15.2 editable: true -- kind: pypi - name: raw-mesh - version: 0.1.0 - path: examples/python/raw_mesh - sha256: 9006b1b7ca8bd9c90ba0bf0d7a00641b7dd13a6de76a2828f79ec5b853a4ef98 - requires_dist: - - numpy - - requests>=2.31,<3 - - rerun-sdk - - trimesh==3.15.2 - editable: true - kind: conda name: rdma-core version: '52.0' @@ -38645,14 +38254,14 @@ packages: - kind: pypi name: regex version: 2024.5.15 - url: https://files.pythonhosted.org/packages/2b/8b/1801c93783cc86bc72ed96f836ee81ea1e42c9f7bbf193aece9878c3fae5/regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl - sha256: c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656 + url: https://files.pythonhosted.org/packages/ef/9b/0aa55fc101c803869c13b389b718b15810592d2df35b1af15ff5b6f48e16/regex-2024.5.15-cp311-cp311-win_amd64.whl + sha256: 9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201 requires_python: '>=3.8' - kind: pypi name: regex version: 2024.5.15 - url: https://files.pythonhosted.org/packages/39/29/8158a6e69e97b9c72fab0b46fe4d57c789d07ef91fe4afde23721e7cac61/regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f + url: https://files.pythonhosted.org/packages/2b/8b/1801c93783cc86bc72ed96f836ee81ea1e42c9f7bbf193aece9878c3fae5/regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl + sha256: c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656 requires_python: '>=3.8' - kind: pypi name: regex @@ -38669,8 +38278,8 @@ packages: - kind: pypi name: regex version: 2024.5.15 - url: https://files.pythonhosted.org/packages/ef/9b/0aa55fc101c803869c13b389b718b15810592d2df35b1af15ff5b6f48e16/regex-2024.5.15-cp311-cp311-win_amd64.whl - sha256: 9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201 + url: https://files.pythonhosted.org/packages/39/29/8158a6e69e97b9c72fab0b46fe4d57c789d07ef91fe4afde23721e7cac61/regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f requires_python: '>=3.8' - kind: pypi name: requests @@ -38698,21 +38307,9 @@ packages: - watchfiles ; extra == 'dev' - kind: pypi name: rerun-notebook - version: 0.19.0a1+dev - path: rerun_notebook - sha256: 746f1bc006974c3c515212908924490e79e892b54bcdfbaa53c5b88e0f3732c1 - requires_dist: - - anywidget - - jupyter-ui-poll - - watchfiles ; extra == 'dev' - - jupyterlab ; extra == 'dev' - - hatch ; extra == 'dev' - editable: true -- kind: pypi - name: rerun-notebook - version: 0.19.0a1+dev + version: 0.19.0a2 path: rerun_notebook - sha256: 746f1bc006974c3c515212908924490e79e892b54bcdfbaa53c5b88e0f3732c1 + sha256: bd617f21c499675c3a72dfe727aade2ccde81dc7c53e76c3982f5172c3c37ecb requires_dist: - anywidget - jupyter-ui-poll @@ -38723,8 +38320,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/30/5f/ce02381b9d7e1e14f60c421c76dce12b7d823690181784780b30266017b1/rerun_sdk-0.17.0-cp38-abi3-macosx_10_12_x86_64.whl - sha256: abd34f746eada83b8bb0bc50007183151981d7ccf18306f3d42165819a3f6fcb + url: https://files.pythonhosted.org/packages/8c/28/92423fe9673b738c180fb5b6b8ea4203fe4b02c1d20b06b7fae79d11cc24/rerun_sdk-0.17.0-cp38-abi3-win_amd64.whl + sha256: 34e5595a326cbdddfebdf00b08e877358c564fce74cc8c6d617fc89ef3a6aa70 requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -38737,8 +38334,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/87/0a/b5fe1ffea700eeaa8d28817a92ad3cb4a7d56dc4af45de76ea412cfc5cd5/rerun_sdk-0.17.0-cp38-abi3-manylinux_2_31_aarch64.whl - sha256: ad55807abafb01e527846742e087819aac8e103f1ec15aadc563a4038bb44e1d + url: https://files.pythonhosted.org/packages/d9/74/6c1ff0c8dbe6da09ceb5ea838a72382fa3131ef6bb9377a30003299743fa/rerun_sdk-0.17.0-cp38-abi3-manylinux_2_31_x86_64.whl + sha256: 9d41f1f475270b1e0d50ddb8cb62e0d828988f0c371ac8457af25c8be5aa1dc0 requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -38751,8 +38348,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/8c/28/92423fe9673b738c180fb5b6b8ea4203fe4b02c1d20b06b7fae79d11cc24/rerun_sdk-0.17.0-cp38-abi3-win_amd64.whl - sha256: 34e5595a326cbdddfebdf00b08e877358c564fce74cc8c6d617fc89ef3a6aa70 + url: https://files.pythonhosted.org/packages/30/5f/ce02381b9d7e1e14f60c421c76dce12b7d823690181784780b30266017b1/rerun_sdk-0.17.0-cp38-abi3-macosx_10_12_x86_64.whl + sha256: abd34f746eada83b8bb0bc50007183151981d7ccf18306f3d42165819a3f6fcb requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -38779,8 +38376,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/d9/74/6c1ff0c8dbe6da09ceb5ea838a72382fa3131ef6bb9377a30003299743fa/rerun_sdk-0.17.0-cp38-abi3-manylinux_2_31_x86_64.whl - sha256: 9d41f1f475270b1e0d50ddb8cb62e0d828988f0c371ac8457af25c8be5aa1dc0 + url: https://files.pythonhosted.org/packages/87/0a/b5fe1ffea700eeaa8d28817a92ad3cb4a7d56dc4af45de76ea412cfc5cd5/rerun_sdk-0.17.0-cp38-abi3-manylinux_2_31_aarch64.whl + sha256: ad55807abafb01e527846742e087819aac8e103f1ec15aadc563a4038bb44e1d requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -38792,9 +38389,9 @@ packages: requires_python: '>=3.8,<3.13' - kind: pypi name: rerun-sdk - version: 0.19.0a1+dev + version: 0.19.0a2 path: rerun_py - sha256: 1a643000ba144557c60764678f4f422425e07e100b4d2e7fbceca6a72f923a47 + sha256: 498c80e631847223d0da7185901724fca71b55c526efc7f95e41bbf64ce42134 requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -38802,7 +38399,7 @@ packages: - pyarrow>=14.0.2 - typing-extensions>=4.5 - pytest==7.1.2 ; extra == 'tests' - - rerun-notebook==0.19.0a1+dev ; extra == 'notebook' + - rerun-notebook==0.19.0a2 ; extra == 'notebook' requires_python: '>=3.8,<3.13' editable: true - kind: pypi @@ -38831,18 +38428,6 @@ packages: - rerun-sdk - tqdm editable: true -- kind: pypi - name: rgbd - version: 0.1.0 - path: examples/python/rgbd - sha256: b2ef153b0bedd672c3e0ce89b7be1f64f4344b2b75d71748899faea270383fa2 - requires_dist: - - numpy - - opencv-python>4.6 - - requests>=2.31,<3 - - rerun-sdk - - tqdm - editable: true - kind: conda name: rhash version: 1.4.4 @@ -38925,8 +38510,8 @@ packages: - kind: pypi name: rpds-py version: 0.19.1 - url: https://files.pythonhosted.org/packages/36/b8/f269fed9aee00fbe96f24e016be76ba685794bc75d3fd30bd88953b474d0/rpds_py-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: c34f751bf67cab69638564eee34023909380ba3e0d8ee7f6fe473079bf93f09b + url: https://files.pythonhosted.org/packages/e8/75/3280074a72a2098e422e371b5a9ea554e1eb6a0b282dff299928d47c1617/rpds_py-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 902cf4739458852fe917104365ec0efbea7d29a15e4276c96a8d33e6ed8ec137 requires_python: '>=3.8' - kind: pypi name: rpds-py @@ -38937,8 +38522,8 @@ packages: - kind: pypi name: rpds-py version: 0.19.1 - url: https://files.pythonhosted.org/packages/e8/75/3280074a72a2098e422e371b5a9ea554e1eb6a0b282dff299928d47c1617/rpds_py-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 902cf4739458852fe917104365ec0efbea7d29a15e4276c96a8d33e6ed8ec137 + url: https://files.pythonhosted.org/packages/36/b8/f269fed9aee00fbe96f24e016be76ba685794bc75d3fd30bd88953b474d0/rpds_py-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: c34f751bf67cab69638564eee34023909380ba3e0d8ee7f6fe473079bf93f09b requires_python: '>=3.8' - kind: pypi name: rrt-star @@ -38949,15 +38534,6 @@ packages: - numpy - rerun-sdk editable: true -- kind: pypi - name: rrt-star - version: 0.1.0 - path: examples/python/rrt_star - sha256: 41993fc9e48ad077ad59ee5918ccc59c86628fd3d8ea4d36bd0706e9880ce6df - requires_dist: - - numpy - - rerun-sdk - editable: true - kind: pypi name: rsa version: '4.9' @@ -39101,8 +38677,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl - sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe + url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl + sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -39141,8 +38717,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/85/f8/13934886b30f4429a480ee24be217cefc279f1d40e1cf0250b327404ab82/safetensors-0.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e9afd5358719f1b2cf425fad638fc3c887997d6782da317096877e5b15b2ce93 + url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -39181,8 +38757,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a + url: https://files.pythonhosted.org/packages/85/f8/13934886b30f4429a480ee24be217cefc279f1d40e1cf0250b327404ab82/safetensors-0.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e9afd5358719f1b2cf425fad638fc3c887997d6782da317096877e5b15b2ce93 requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -39221,8 +38797,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl - sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 + url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl + sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -39301,8 +38877,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/3c/f6/be8b16d8ab6ebf19057877c2aec905cbd438dd92ca64b8efe9e9af008fa3/scikit_image-0.24.0-cp311-cp311-macosx_12_0_arm64.whl - sha256: 190ebde80b4470fe8838764b9b15f232a964f1a20391663e31008d76f0c696f7 + url: https://files.pythonhosted.org/packages/50/b2/d5e97115733e2dc657e99868ae0237705b79d0c81f6ced21b8f0799a30d1/scikit_image-0.24.0-cp311-cp311-win_amd64.whl + sha256: dacf591ac0c272a111181afad4b788a27fe70d213cfddd631d151cbc34f8ca2c requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39368,8 +38944,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/50/b2/d5e97115733e2dc657e99868ae0237705b79d0c81f6ced21b8f0799a30d1/scikit_image-0.24.0-cp311-cp311-win_amd64.whl - sha256: dacf591ac0c272a111181afad4b788a27fe70d213cfddd631d151cbc34f8ca2c + url: https://files.pythonhosted.org/packages/90/e3/564beb0c78bf83018a146dfcdc959c99c10a0d136480b932a350c852adbc/scikit_image-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 272909e02a59cea3ed4aa03739bb88df2625daa809f633f40b5053cf09241831 requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39435,8 +39011,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/90/e3/564beb0c78bf83018a146dfcdc959c99c10a0d136480b932a350c852adbc/scikit_image-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 272909e02a59cea3ed4aa03739bb88df2625daa809f633f40b5053cf09241831 + url: https://files.pythonhosted.org/packages/b8/2e/3a949995f8fc2a65b15a4964373e26c5601cb2ea68f36b115571663e7a38/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 59c98cc695005faf2b79904e4663796c977af22586ddf1b12d6af2fa22842dc2 requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39502,8 +39078,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/ad/96/138484302b8ec9a69cdf65e8d4ab47a640a3b1a8ea3c437e1da3e1a5a6b8/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fa27b3a0dbad807b966b8db2d78da734cb812ca4787f7fbb143764800ce2fa9c + url: https://files.pythonhosted.org/packages/3c/f6/be8b16d8ab6ebf19057877c2aec905cbd438dd92ca64b8efe9e9af008fa3/scikit_image-0.24.0-cp311-cp311-macosx_12_0_arm64.whl + sha256: 190ebde80b4470fe8838764b9b15f232a964f1a20391663e31008d76f0c696f7 requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39569,8 +39145,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/b8/2e/3a949995f8fc2a65b15a4964373e26c5601cb2ea68f36b115571663e7a38/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 59c98cc695005faf2b79904e4663796c977af22586ddf1b12d6af2fa22842dc2 + url: https://files.pythonhosted.org/packages/ad/96/138484302b8ec9a69cdf65e8d4ab47a640a3b1a8ea3c437e1da3e1a5a6b8/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fa27b3a0dbad807b966b8db2d78da734cb812ca4787f7fbb143764800ce2fa9c requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39636,8 +39212,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/03/86/ab9f95e338c5ef5b4e79463ee91e55aae553213835e59bf038bc0cc21bf8/scikit_learn-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 154297ee43c0b83af12464adeab378dee2d0a700ccd03979e2b821e7dd7cc1c2 + url: https://files.pythonhosted.org/packages/5d/55/0403bf2031250ac982c8053397889fbc5a3a2b3798b913dae4f51c3af6a4/scikit_learn-1.5.1-cp311-cp311-win_amd64.whl + sha256: 9a07f90846313a7639af6a019d849ff72baadfa4c74c778821ae0fad07b7275b requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39697,8 +39273,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/32/63/ed228892adad313aab0d0f9261241e7bf1efe36730a2788ad424bcad00ca/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 689b6f74b2c880276e365fe84fe4f1befd6a774f016339c65655eaff12e10cbf + url: https://files.pythonhosted.org/packages/03/86/ab9f95e338c5ef5b4e79463ee91e55aae553213835e59bf038bc0cc21bf8/scikit_learn-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 154297ee43c0b83af12464adeab378dee2d0a700ccd03979e2b821e7dd7cc1c2 requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39758,8 +39334,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/5d/55/0403bf2031250ac982c8053397889fbc5a3a2b3798b913dae4f51c3af6a4/scikit_learn-1.5.1-cp311-cp311-win_amd64.whl - sha256: 9a07f90846313a7639af6a019d849ff72baadfa4c74c778821ae0fad07b7275b + url: https://files.pythonhosted.org/packages/c1/f8/fd3fa610cac686952d8c78b8b44cf5263c6c03885bd8e5d5819c684b44e8/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 909144d50f367a513cee6090873ae582dba019cb3fca063b38054fa42704c3a4 requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39880,8 +39456,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/c1/f8/fd3fa610cac686952d8c78b8b44cf5263c6c03885bd8e5d5819c684b44e8/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 909144d50f367a513cee6090873ae582dba019cb3fca063b38054fa42704c3a4 + url: https://files.pythonhosted.org/packages/32/63/ed228892adad313aab0d0f9261241e7bf1efe36730a2788ad424bcad00ca/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 689b6f74b2c880276e365fe84fe4f1befd6a774f016339c65655eaff12e10cbf requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39941,8 +39517,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/10/55/d6096721c0f0d7e7369da9660a854c14e6379ab7aba603ea5d492d77fa23/scipy-1.14.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6d056a8709ccda6cf36cdd2eac597d13bc03dba38360f418560a93050c76a16e + url: https://files.pythonhosted.org/packages/91/1d/0484130df7e33e044da88a091827d6441b77f907075bf7bbe145857d6590/scipy-1.14.0-cp311-cp311-win_amd64.whl + sha256: 5b083c8940028bb7e0b4172acafda6df762da1927b9091f9611b0bcd8676f2bc requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -39983,8 +39559,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/56/95/1a3a04b5facab8287325ad2335dbb6b78b98d73690c832099c9c498f7a4d/scipy-1.14.0-cp311-cp311-macosx_12_0_arm64.whl - sha256: f0a50da861a7ec4573b7c716b2ebdcdf142b66b756a0d392c236ae568b3a93fb + url: https://files.pythonhosted.org/packages/10/55/d6096721c0f0d7e7369da9660a854c14e6379ab7aba603ea5d492d77fa23/scipy-1.14.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6d056a8709ccda6cf36cdd2eac597d13bc03dba38360f418560a93050c76a16e requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -40067,8 +39643,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/89/bb/80c9c98d887c855710fd31fc5ae5574133e98203b3475b07579251803662/scipy-1.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 9e3154691b9f7ed73778d746da2df67a19d046a6c8087c8b385bc4cdb2cfca74 + url: https://files.pythonhosted.org/packages/56/95/1a3a04b5facab8287325ad2335dbb6b78b98d73690c832099c9c498f7a4d/scipy-1.14.0-cp311-cp311-macosx_12_0_arm64.whl + sha256: f0a50da861a7ec4573b7c716b2ebdcdf142b66b756a0d392c236ae568b3a93fb requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -40109,8 +39685,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/91/1d/0484130df7e33e044da88a091827d6441b77f907075bf7bbe145857d6590/scipy-1.14.0-cp311-cp311-win_amd64.whl - sha256: 5b083c8940028bb7e0b4172acafda6df762da1927b9091f9611b0bcd8676f2bc + url: https://files.pythonhosted.org/packages/89/bb/80c9c98d887c855710fd31fc5ae5574133e98203b3475b07579251803662/scipy-1.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 9e3154691b9f7ed73778d746da2df67a19d046a6c8087c8b385bc4cdb2cfca74 requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -40160,7 +39736,7 @@ packages: - kind: pypi name: segment-anything version: '1.0' - url: git+https://github.com/facebookresearch/segment-anything.git@526fd066dea338ba2ca08886853bd37ffd6a8aec + url: git+https://github.com/facebookresearch/segment-anything.git@dca509fe793f601edb92606367a655c15ac00fdf requires_dist: - matplotlib ; extra == 'all' - pycocotools ; extra == 'all' @@ -40174,7 +39750,7 @@ packages: - kind: pypi name: segment-anything version: '1.0' - url: git+https://github.com/facebookresearch/segment-anything.git@dca509fe793f601edb92606367a655c15ac00fdf + url: git+https://github.com/facebookresearch/segment-anything.git@526fd066dea338ba2ca08886853bd37ffd6a8aec requires_dist: - matplotlib ; extra == 'all' - pycocotools ; extra == 'all' @@ -40200,21 +39776,6 @@ packages: - torchvision - tqdm editable: true -- kind: pypi - name: segment-anything-model - version: 0.1.0 - path: examples/python/segment_anything_model - sha256: 85bc241bedf212c63a39d0251a9dcc0fb3a435087a024d4eafd7f49342a75926 - requires_dist: - - segment-anything @ git+https://github.com/facebookresearch/segment-anything.git - - numpy - - opencv-python - - requests>=2.31,<3 - - rerun-sdk - - torch==2.2.2 - - torchvision - - tqdm - editable: true - kind: conda name: semver version: 2.13.0 @@ -40397,8 +39958,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/29/3d/0d3ab80860cda6afbce9736fa1f091f452092d344fdd4e3c65e5fe7b1111/shapely-2.0.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5bbfb048a74cf273db9091ff3155d373020852805a37dfc846ab71dde4be93ec + url: https://files.pythonhosted.org/packages/ec/1b/092fff53cbeced411eed2717592e31cadd3e52f0ebaba5f2df3f34913f96/shapely-2.0.5-cp311-cp311-win_amd64.whl + sha256: 6c6b78c0007a34ce7144f98b7418800e0a6a5d9a762f2244b00ea560525290c9 requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -40412,8 +39973,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/7e/4e/4e83b9f3d7f0ce523c92bdf3dfe0292738d8ad2b589971390d6205bc843e/shapely-2.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 0f8e71bb9a46814019f6644c4e2560a09d44b80100e46e371578f35eaaa9da1c + url: https://files.pythonhosted.org/packages/29/3d/0d3ab80860cda6afbce9736fa1f091f452092d344fdd4e3c65e5fe7b1111/shapely-2.0.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5bbfb048a74cf273db9091ff3155d373020852805a37dfc846ab71dde4be93ec requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -40427,8 +39988,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/80/68/6b51b7587547f6bbd0965cf957505a0ebec93510e840572a983003b3a0a9/shapely-2.0.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: 93be600cbe2fbaa86c8eb70656369f2f7104cd231f0d6585c7d0aa555d6878b8 + url: https://files.pythonhosted.org/packages/7e/4e/4e83b9f3d7f0ce523c92bdf3dfe0292738d8ad2b589971390d6205bc843e/shapely-2.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 0f8e71bb9a46814019f6644c4e2560a09d44b80100e46e371578f35eaaa9da1c requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -40442,8 +40003,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/ec/1b/092fff53cbeced411eed2717592e31cadd3e52f0ebaba5f2df3f34913f96/shapely-2.0.5-cp311-cp311-win_amd64.whl - sha256: 6c6b78c0007a34ce7144f98b7418800e0a6a5d9a762f2244b00ea560525290c9 + url: https://files.pythonhosted.org/packages/80/68/6b51b7587547f6bbd0965cf957505a0ebec93510e840572a983003b3a0a9/shapely-2.0.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: 93be600cbe2fbaa86c8eb70656369f2f7104cd231f0d6585c7d0aa555d6878b8 requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -40477,14 +40038,6 @@ packages: requires_dist: - rerun-sdk editable: true -- kind: pypi - name: shared-recording - version: 0.1.0 - path: examples/python/shared_recording - sha256: 6f605379e813578a2304663522ed82ab2fd6486cee725b969abd533b5ac8072f - requires_dist: - - rerun-sdk - editable: true - kind: pypi name: shellingham version: 1.5.4 @@ -40504,19 +40057,6 @@ packages: - scikit-learn>=1.1.3 - trimesh==3.15.2 editable: true -- kind: pypi - name: signed-distance-fields - version: 0.1.0 - path: examples/python/signed_distance_fields - sha256: 32880a8a3883c6aa03c709fe9138ba6b939633562ff98ca27fc22afc3d69f08a - requires_dist: - - mesh-to-sdf @ git+https://github.com/marian42/mesh_to_sdf.git - - numpy - - requests>=2.31,<3 - - rerun-sdk - - scikit-learn>=1.1.3 - - trimesh==3.15.2 - editable: true - kind: conda name: sigtool version: 0.1.3 @@ -40550,14 +40090,14 @@ packages: - kind: pypi name: simplejson version: 3.19.2 - url: https://files.pythonhosted.org/packages/53/a0/4430915cac272de9af75287f566cd1f06dffb69b3e9fa24b3c16b066470b/simplejson-3.19.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 08889f2f597ae965284d7b52a5c3928653a9406d88c93e3161180f0abc2433ba + url: https://files.pythonhosted.org/packages/b6/8e/3e12d122dfdf549a8d12eaf39954ee39f2027060aa38b63430f8ab3244e7/simplejson-3.19.2-cp311-cp311-win_amd64.whl + sha256: 9300aee2a8b5992d0f4293d88deb59c218989833e3396c824b69ba330d04a589 requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson version: 3.19.2 - url: https://files.pythonhosted.org/packages/70/c1/816573ae91aebf06a0fefd8ea30ca43127aa58e68684d2ddfe17c8457afb/simplejson-3.19.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 4d36081c0b1c12ea0ed62c202046dca11438bee48dd5240b7c8de8da62c620e9 + url: https://files.pythonhosted.org/packages/bc/eb/2bd4a6ec98329158f6855520596e9f2e521e2239e292d43fe1c58cf83a9b/simplejson-3.19.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: adcb3332979cbc941b8fff07181f06d2b608625edc0a4d8bc3ffc0be414ad0c4 requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson @@ -40568,14 +40108,14 @@ packages: - kind: pypi name: simplejson version: 3.19.2 - url: https://files.pythonhosted.org/packages/b6/8e/3e12d122dfdf549a8d12eaf39954ee39f2027060aa38b63430f8ab3244e7/simplejson-3.19.2-cp311-cp311-win_amd64.whl - sha256: 9300aee2a8b5992d0f4293d88deb59c218989833e3396c824b69ba330d04a589 + url: https://files.pythonhosted.org/packages/53/a0/4430915cac272de9af75287f566cd1f06dffb69b3e9fa24b3c16b066470b/simplejson-3.19.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 08889f2f597ae965284d7b52a5c3928653a9406d88c93e3161180f0abc2433ba requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson version: 3.19.2 - url: https://files.pythonhosted.org/packages/bc/eb/2bd4a6ec98329158f6855520596e9f2e521e2239e292d43fe1c58cf83a9b/simplejson-3.19.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: adcb3332979cbc941b8fff07181f06d2b608625edc0a4d8bc3ffc0be414ad0c4 + url: https://files.pythonhosted.org/packages/70/c1/816573ae91aebf06a0fefd8ea30ca43127aa58e68684d2ddfe17c8457afb/simplejson-3.19.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 4d36081c0b1c12ea0ed62c202046dca11438bee48dd5240b7c8de8da62c620e9 requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: six @@ -40690,8 +40230,8 @@ packages: - kind: pypi name: sounddevice version: 0.4.7 - url: https://files.pythonhosted.org/packages/1c/9c/d8de668a462b7a326d9f697dfa2adb6fbde07cc468cc7cdcf51cbe975d56/sounddevice-0.4.7-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl - sha256: d6ddfd341ad7412b14ca001f2c4dbf5fa2503bdc9eb15ad2c3105f6c260b698a + url: https://files.pythonhosted.org/packages/d4/09/bfdd393f1bb1b90b4a6849b84972b7059c95e36818cc489922228d58cc63/sounddevice-0.4.7-py3-none-win_amd64.whl + sha256: 0c8b3543da1496f282b66a7bc54b755577ba638b1af06c146d4ac7f39d86b548 requires_dist: - cffi>=1.0 - numpy ; extra == 'numpy' @@ -40699,8 +40239,8 @@ packages: - kind: pypi name: sounddevice version: 0.4.7 - url: https://files.pythonhosted.org/packages/46/ea/e9196f01ec3c5ad537e1bb83fe08da3bacfbdfee8a872c461e491f489801/sounddevice-0.4.7-py3-none-any.whl - sha256: 1c3f18bfa4d9a257f5715f2ab83f2c0eb412a09f3e6a9fa73720886ca88f6bc7 + url: https://files.pythonhosted.org/packages/1c/9c/d8de668a462b7a326d9f697dfa2adb6fbde07cc468cc7cdcf51cbe975d56/sounddevice-0.4.7-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl + sha256: d6ddfd341ad7412b14ca001f2c4dbf5fa2503bdc9eb15ad2c3105f6c260b698a requires_dist: - cffi>=1.0 - numpy ; extra == 'numpy' @@ -40708,8 +40248,8 @@ packages: - kind: pypi name: sounddevice version: 0.4.7 - url: https://files.pythonhosted.org/packages/d4/09/bfdd393f1bb1b90b4a6849b84972b7059c95e36818cc489922228d58cc63/sounddevice-0.4.7-py3-none-win_amd64.whl - sha256: 0c8b3543da1496f282b66a7bc54b755577ba638b1af06c146d4ac7f39d86b548 + url: https://files.pythonhosted.org/packages/46/ea/e9196f01ec3c5ad537e1bb83fe08da3bacfbdfee8a872c461e491f489801/sounddevice-0.4.7-py3-none-any.whl + sha256: 1c3f18bfa4d9a257f5715f2ab83f2c0eb412a09f3e6a9fa73720886ca88f6bc7 requires_dist: - cffi>=1.0 - numpy ; extra == 'numpy' @@ -40742,14 +40282,6 @@ packages: requires_dist: - rerun-sdk editable: true -- kind: pypi - name: stdio - version: 0.1.0 - path: examples/python/stdio - sha256: 15fb60d3e1c8b7b2d1a4dfcc223bddb267451e8ef7534d42f663d116166d92e2 - requires_dist: - - rerun-sdk - editable: true - kind: pypi name: stringcase version: 1.2.0 @@ -40767,18 +40299,6 @@ packages: - rerun-sdk - tqdm editable: true -- kind: pypi - name: structure-from-motion - version: 0.1.0 - path: examples/python/structure_from_motion - sha256: b20b79aa7bb2b4225b37d3cb28872a70dc7e9ab2ca9ab138b90d60fc8d7b4c15 - requires_dist: - - opencv-python>4.6 - - numpy - - requests>=2.31,<3 - - rerun-sdk - - tqdm - editable: true - kind: conda name: svt-av1 version: 2.1.2 @@ -41300,8 +40820,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/36/c6/537f22b57e6003904d35d07962dbde2f2e9bdd791d0241da976a4c7f8194/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc + url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl + sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -41318,8 +40838,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl - sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 + url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -41336,8 +40856,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 + url: https://files.pythonhosted.org/packages/36/c6/537f22b57e6003904d35d07962dbde2f2e9bdd791d0241da976a4c7f8194/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -41354,8 +40874,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa + url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -41372,8 +40892,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 + url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -41430,8 +40950,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41457,8 +40977,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl - sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41484,8 +41004,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41511,8 +41031,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl - sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 + url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl + sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41538,8 +41058,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41565,8 +41085,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d + url: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl + sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 requires_dist: - numpy - torch==2.2.2 @@ -41598,8 +41118,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl - sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 + url: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d requires_dist: - numpy - torch==2.2.2 @@ -41609,8 +41129,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl - sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 + url: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl + sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 requires_dist: - numpy - torch==2.2.2 @@ -41620,32 +41140,32 @@ packages: - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/00/d9/c33be3c1a7564f7d42d87a8d186371a75fd142097076767a5c27da941fef/tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl - sha256: 163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8 + url: https://files.pythonhosted.org/packages/d9/2f/3f2f05e84a7aff787a96d5fb06821323feb370fe0baed4db6ea7b1088f32/tornado-6.4.1-cp38-abi3-win_amd64.whl + sha256: b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7 requires_python: '>=3.8' - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/13/cf/786b8f1e6fe1c7c675e79657448178ad65e41c1c9765ef82e7f6f765c4c5/tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4 + url: https://files.pythonhosted.org/packages/2e/0f/721e113a2fac2f1d7d124b3279a1da4c77622e104084f56119875019ffab/tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl + sha256: 6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14 requires_python: '>=3.8' - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/22/d4/54f9d12668b58336bd30defe0307e6c61589a3e687b05c366f804b7faaf0/tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3 + url: https://files.pythonhosted.org/packages/13/cf/786b8f1e6fe1c7c675e79657448178ad65e41c1c9765ef82e7f6f765c4c5/tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4 requires_python: '>=3.8' - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/2e/0f/721e113a2fac2f1d7d124b3279a1da4c77622e104084f56119875019ffab/tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl - sha256: 6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14 + url: https://files.pythonhosted.org/packages/00/d9/c33be3c1a7564f7d42d87a8d186371a75fd142097076767a5c27da941fef/tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl + sha256: 163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8 requires_python: '>=3.8' - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/d9/2f/3f2f05e84a7aff787a96d5fb06821323feb370fe0baed4db6ea7b1088f32/tornado-6.4.1-cp38-abi3-win_amd64.whl - sha256: b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7 + url: https://files.pythonhosted.org/packages/22/d4/54f9d12668b58336bd30defe0307e6c61589a3e687b05c366f804b7faaf0/tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3 requires_python: '>=3.8' - kind: pypi name: tqdm @@ -42868,14 +42388,8 @@ packages: - kind: pypi name: uv version: 0.2.26 - url: https://files.pythonhosted.org/packages/0f/b6/cbb68a3b7faf7afa406d38b6d94065f759cac1b13a0a15dffa5bf7d7b60f/uv-0.2.26-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 65120080bbd2f2ce47e92f6065e223f2f416feb3a323ea9574d3e993b7ebde9f - requires_python: '>=3.8' -- kind: pypi - name: uv - version: 0.2.26 - url: https://files.pythonhosted.org/packages/7a/30/24a74c0ca887d3a75821814d292e1001571d574c4c2b217a858b09ce8b88/uv-0.2.26-py3-none-macosx_10_12_x86_64.whl - sha256: fd3e850921f0d51d093aaeb76d190829eefdc0345439b8f6c06103a0463cc451 + url: https://files.pythonhosted.org/packages/b3/2c/8d18a2e39015ad132bfa8d8ff31b8bad5cea6760db0534963d54944b13f1/uv-0.2.26-py3-none-macosx_11_0_arm64.whl + sha256: 3117aabd606cbe70a3a1589301ce14d578f3f62a46025b26e251b664b01b3728 requires_python: '>=3.8' - kind: pypi name: uv @@ -42886,8 +42400,8 @@ packages: - kind: pypi name: uv version: 0.2.26 - url: https://files.pythonhosted.org/packages/b3/2c/8d18a2e39015ad132bfa8d8ff31b8bad5cea6760db0534963d54944b13f1/uv-0.2.26-py3-none-macosx_11_0_arm64.whl - sha256: 3117aabd606cbe70a3a1589301ce14d578f3f62a46025b26e251b664b01b3728 + url: https://files.pythonhosted.org/packages/7a/30/24a74c0ca887d3a75821814d292e1001571d574c4c2b217a858b09ce8b88/uv-0.2.26-py3-none-macosx_10_12_x86_64.whl + sha256: fd3e850921f0d51d093aaeb76d190829eefdc0345439b8f6c06103a0463cc451 requires_python: '>=3.8' - kind: pypi name: uv @@ -42895,17 +42409,23 @@ packages: url: https://files.pythonhosted.org/packages/ee/d1/d0311b79198f5f07809edcb6b71f38f8e8e0d848194ff0f5bfcd1cd941fe/uv-0.2.26-py3-none-win_amd64.whl sha256: 05949e0135d5093d555f17ca6701e5939547d8a656bec003b7986e3540533348 requires_python: '>=3.8' +- kind: pypi + name: uv + version: 0.2.26 + url: https://files.pythonhosted.org/packages/0f/b6/cbb68a3b7faf7afa406d38b6d94065f759cac1b13a0a15dffa5bf7d7b60f/uv-0.2.26-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 65120080bbd2f2ce47e92f6065e223f2f416feb3a323ea9574d3e993b7ebde9f + requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.27 - url: https://files.pythonhosted.org/packages/be/53/b3e7e74acc2cf91861abfaabf11255df26d82871e1d3fcfec1c3c9b6dcd0/uv-0.2.27-py3-none-macosx_11_0_arm64.whl - sha256: 8a44fc58726f353645c64ccde00338e73fa97aa42bbeb3bd6a8269c0b9386954 + url: https://files.pythonhosted.org/packages/db/a7/b4a48f4cd49fab545c6e5bb743e3569aff0869625bb22bd233d958fd15a5/uv-0.2.27-py3-none-manylinux_2_28_aarch64.whl + sha256: d33d54d8119bb5dd52c52f3d78efd61064ae650d0105b65b471eb0de48f5c4ba requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.27 - url: https://files.pythonhosted.org/packages/ce/c8/553675aaa47659254efe2f081763d3075908726fa9b23b4a345105402e8e/uv-0.2.27-py3-none-macosx_10_12_x86_64.whl - sha256: f0ee3caf45a0be203e6edff62caa9e7cdc3863172e15869c24fc41847c83e5e5 + url: https://files.pythonhosted.org/packages/ed/1d/74d7009e57a85c6baedfb7bdf51481523b4a931eddb106c89f287dc278c8/uv-0.2.27-py3-none-win_amd64.whl + sha256: 7921c9eb9feb3b7a9cb6f4afab58718a5a07752d834c2de72b7d294bff963789 requires_python: '>=3.8' - kind: pypi name: uv @@ -42916,26 +42436,26 @@ packages: - kind: pypi name: uv version: 0.2.27 - url: https://files.pythonhosted.org/packages/db/a7/b4a48f4cd49fab545c6e5bb743e3569aff0869625bb22bd233d958fd15a5/uv-0.2.27-py3-none-manylinux_2_28_aarch64.whl - sha256: d33d54d8119bb5dd52c52f3d78efd61064ae650d0105b65b471eb0de48f5c4ba + url: https://files.pythonhosted.org/packages/ce/c8/553675aaa47659254efe2f081763d3075908726fa9b23b4a345105402e8e/uv-0.2.27-py3-none-macosx_10_12_x86_64.whl + sha256: f0ee3caf45a0be203e6edff62caa9e7cdc3863172e15869c24fc41847c83e5e5 requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.27 - url: https://files.pythonhosted.org/packages/ed/1d/74d7009e57a85c6baedfb7bdf51481523b4a931eddb106c89f287dc278c8/uv-0.2.27-py3-none-win_amd64.whl - sha256: 7921c9eb9feb3b7a9cb6f4afab58718a5a07752d834c2de72b7d294bff963789 + url: https://files.pythonhosted.org/packages/be/53/b3e7e74acc2cf91861abfaabf11255df26d82871e1d3fcfec1c3c9b6dcd0/uv-0.2.27-py3-none-macosx_11_0_arm64.whl + sha256: 8a44fc58726f353645c64ccde00338e73fa97aa42bbeb3bd6a8269c0b9386954 requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.28 - url: https://files.pythonhosted.org/packages/69/68/34dc06721be38c4d90c717a34d8d0f7441d83d8f0efb2126a7026204e7dc/uv-0.2.28-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 8fc4185ee3bc644e38421a82a942fa5c7864d6eeaa04fd59e1ae577e2e5b76ea + url: https://files.pythonhosted.org/packages/80/d2/b8206aa8b4de05388cae473f87a06e6be80cfcc6ba6dd8313a4be9647252/uv-0.2.28-py3-none-manylinux_2_28_aarch64.whl + sha256: 894a9929f8deb9c15cf84c98fb89e8e2c3dcf6e9fd6da8c81e7b9a22c86d661e requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.28 - url: https://files.pythonhosted.org/packages/80/d2/b8206aa8b4de05388cae473f87a06e6be80cfcc6ba6dd8313a4be9647252/uv-0.2.28-py3-none-manylinux_2_28_aarch64.whl - sha256: 894a9929f8deb9c15cf84c98fb89e8e2c3dcf6e9fd6da8c81e7b9a22c86d661e + url: https://files.pythonhosted.org/packages/69/68/34dc06721be38c4d90c717a34d8d0f7441d83d8f0efb2126a7026204e7dc/uv-0.2.28-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 8fc4185ee3bc644e38421a82a942fa5c7864d6eeaa04fd59e1ae577e2e5b76ea requires_python: '>=3.8' - kind: conda name: vc @@ -43157,14 +42677,14 @@ packages: - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 + url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 + url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 requires_python: '>=3.6' - kind: pypi name: wrapt @@ -43175,8 +42695,8 @@ packages: - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 + url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 requires_python: '>=3.6' - kind: conda name: x264 @@ -44284,8 +43804,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/63/b6/677e65c095d8e12b66b8f862b069bcf1f1d781b9c9c6f12eb55000d57583/zstandard-0.23.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a + url: https://files.pythonhosted.org/packages/e8/46/66d5b55f4d737dd6ab75851b224abf0afe5774976fe511a54d2eb9063a41/zstandard-0.23.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -44293,8 +43813,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/76/3f/dbafccf19cfeca25bbabf6f2dd81796b7218f768ec400f043edc767015a6/zstandard-0.23.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca + url: https://files.pythonhosted.org/packages/63/b6/677e65c095d8e12b66b8f862b069bcf1f1d781b9c9c6f12eb55000d57583/zstandard-0.23.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -44320,8 +43840,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/e8/46/66d5b55f4d737dd6ab75851b224abf0afe5774976fe511a54d2eb9063a41/zstandard-0.23.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 + url: https://files.pythonhosted.org/packages/76/3f/dbafccf19cfeca25bbabf6f2dd81796b7218f768ec400f043edc767015a6/zstandard-0.23.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' diff --git a/rerun_cpp/src/rerun/c/sdk_info.h b/rerun_cpp/src/rerun/c/sdk_info.h index a5cddb52287f..923a45481ea1 100644 --- a/rerun_cpp/src/rerun/c/sdk_info.h +++ b/rerun_cpp/src/rerun/c/sdk_info.h @@ -2,7 +2,7 @@ /// /// 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.19.0-alpha.1+dev" +#define RERUN_SDK_HEADER_VERSION "0.19.0-alpha.2" /// Major version of the Rerun C SDK. #define RERUN_SDK_HEADER_VERSION_MAJOR 0 diff --git a/rerun_js/web-viewer-react/README.md b/rerun_js/web-viewer-react/README.md index b586d2f7cdac..ac9aa84c12c4 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 6b8a9bd9d7da..c66c3e1eacf7 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.19.0-alpha.1+dev", + "version": "0.19.0-alpha.2", "description": "Embed the Rerun web viewer in your React app", "licenses": [ { @@ -39,7 +39,7 @@ "tsconfig.json" ], "dependencies": { - "@rerun-io/web-viewer": "0.19.0-alpha.1", + "@rerun-io/web-viewer": "0.19.0-alpha.2", "@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 211c3435f852..257cfe64366c 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 b5f41ef8ba09..f419af823d63 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.19.0-alpha.1+dev", + "version": "0.19.0-alpha.2", "description": "Embed the Rerun web viewer in your app", "licenses": [ { diff --git a/rerun_notebook/pyproject.toml b/rerun_notebook/pyproject.toml index 3b315206fad5..fe98c78cbc3e 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.19.0-alpha.1+dev" +version = "0.19.0-alpha.2" dependencies = ["anywidget", "jupyter-ui-poll"] readme = "README.md" keywords = ["rerun", "notebook"] diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index 1d2ab8f4ec82..668706fd7470 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.19.0-alpha.1+dev"] +notebook = ["rerun-notebook==0.19.0-alpha.2"] [project.urls] documentation = "https://www.rerun.io/docs" diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 15ff5149c784..b9b37451ff9f 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -7,8 +7,8 @@ import numpy as np -__version__ = "0.19.0-alpha.1+dev" -__version_info__ = (0, 19, 0, "alpha.1") +__version__ = "0.19.0-alpha.2" +__version_info__ = (0, 19, 0, "alpha.2") # ===================================== # API RE-EXPORTS From 424b9dca55c63da7c53eba25dd18ce213b549971 Mon Sep 17 00:00:00 2001 From: rerun-bot <132550499+rerun-bot@users.noreply.github.com> Date: Sat, 12 Oct 2024 20:12:51 +0200 Subject: [PATCH 21/33] Release 0.19.0-alpha.3 (#7706) --- Cargo.lock | 216 ++--- Cargo.toml | 120 +-- examples/rust/clock/Cargo.toml | 2 +- examples/rust/custom_data_loader/Cargo.toml | 2 +- examples/rust/custom_space_view/Cargo.toml | 2 +- .../rust/custom_store_subscriber/Cargo.toml | 2 +- examples/rust/dna/Cargo.toml | 2 +- examples/rust/extend_viewer_ui/Cargo.toml | 2 +- examples/rust/external_data_loader/Cargo.toml | 2 +- examples/rust/incremental_logging/Cargo.toml | 2 +- examples/rust/log_file/Cargo.toml | 2 +- examples/rust/minimal/Cargo.toml | 2 +- examples/rust/minimal_options/Cargo.toml | 2 +- examples/rust/minimal_serve/Cargo.toml | 2 +- examples/rust/objectron/Cargo.toml | 2 +- examples/rust/raw_mesh/Cargo.toml | 2 +- examples/rust/shared_recording/Cargo.toml | 2 +- examples/rust/spawn_viewer/Cargo.toml | 2 +- examples/rust/stdio/Cargo.toml | 2 +- examples/rust/template/Cargo.toml | 2 +- pixi.lock | 890 +++++++++--------- rerun_cpp/src/rerun/c/sdk_info.h | 2 +- rerun_js/web-viewer-react/README.md | 2 +- rerun_js/web-viewer-react/package.json | 4 +- rerun_js/web-viewer/README.md | 2 +- rerun_js/web-viewer/package.json | 2 +- rerun_notebook/pyproject.toml | 2 +- rerun_py/pyproject.toml | 2 +- rerun_py/rerun_sdk/rerun/__init__.py | 4 +- 29 files changed, 641 insertions(+), 641 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e9b03cfa603..3d4b1a2a5097 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "clock" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -1647,7 +1647,7 @@ checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" [[package]] name = "custom_data_loader" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "re_build_tools", "rerun", @@ -1655,7 +1655,7 @@ dependencies = [ [[package]] name = "custom_space_view" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "mimalloc", "re_crash_handler", @@ -1665,7 +1665,7 @@ dependencies = [ [[package]] name = "custom_store_subscriber" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "re_build_tools", "rerun", @@ -1786,7 +1786,7 @@ dependencies = [ [[package]] name = "dna" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "itertools 0.13.0", "rand", @@ -2289,7 +2289,7 @@ dependencies = [ [[package]] name = "extend_viewer_ui" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "mimalloc", "re_crash_handler", @@ -2942,7 +2942,7 @@ dependencies = [ [[package]] name = "incremental_logging" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -3356,7 +3356,7 @@ dependencies = [ [[package]] name = "log_benchmark" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -3367,7 +3367,7 @@ dependencies = [ [[package]] name = "log_file" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -3496,14 +3496,14 @@ dependencies = [ [[package]] name = "minimal" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "rerun", ] [[package]] name = "minimal_options" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -3513,7 +3513,7 @@ dependencies = [ [[package]] name = "minimal_serve" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "rerun", ] @@ -4117,7 +4117,7 @@ dependencies = [ [[package]] name = "objectron" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -4326,7 +4326,7 @@ dependencies = [ [[package]] name = "plot_dashboard_stress" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -4801,7 +4801,7 @@ checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" [[package]] name = "raw_mesh" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "bytes", @@ -4840,7 +4840,7 @@ dependencies = [ [[package]] name = "re_analytics" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "crossbeam", "directories", @@ -4886,7 +4886,7 @@ dependencies = [ [[package]] name = "re_blueprint_tree" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "itertools 0.13.0", @@ -4905,14 +4905,14 @@ dependencies = [ [[package]] name = "re_build_info" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "serde", ] [[package]] name = "re_build_tools" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "cargo_metadata 0.18.1", @@ -4925,14 +4925,14 @@ dependencies = [ [[package]] name = "re_case" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "convert_case", ] [[package]] name = "re_chunk" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4961,7 +4961,7 @@ dependencies = [ [[package]] name = "re_chunk_store" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -4992,7 +4992,7 @@ dependencies = [ [[package]] name = "re_chunk_store_ui" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "egui_extras", @@ -5007,7 +5007,7 @@ dependencies = [ [[package]] name = "re_component_ui" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "egui_extras", @@ -5024,7 +5024,7 @@ dependencies = [ [[package]] name = "re_context_menu" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "egui_tiles", @@ -5045,7 +5045,7 @@ dependencies = [ [[package]] name = "re_crash_handler" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "backtrace", "econtext", @@ -5058,7 +5058,7 @@ dependencies = [ [[package]] name = "re_data_loader" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5084,7 +5084,7 @@ dependencies = [ [[package]] name = "re_data_source" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "itertools 0.13.0", @@ -5101,7 +5101,7 @@ dependencies = [ [[package]] name = "re_data_ui" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5130,7 +5130,7 @@ dependencies = [ [[package]] name = "re_dataframe" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "itertools 0.13.0", @@ -5150,7 +5150,7 @@ dependencies = [ [[package]] name = "re_dev_tools" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "argh", @@ -5177,7 +5177,7 @@ dependencies = [ [[package]] name = "re_entity_db" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5211,21 +5211,21 @@ dependencies = [ [[package]] name = "re_error" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", ] [[package]] name = "re_format" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "num-traits", ] [[package]] name = "re_format_arrow" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "comfy-table", "re_arrow2", @@ -5235,7 +5235,7 @@ dependencies = [ [[package]] name = "re_int_histogram" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "criterion", "insta", @@ -5246,7 +5246,7 @@ dependencies = [ [[package]] name = "re_log" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "env_logger", "js-sys", @@ -5259,7 +5259,7 @@ dependencies = [ [[package]] name = "re_log_encoding" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "criterion", "ehttp", @@ -5285,7 +5285,7 @@ dependencies = [ [[package]] name = "re_log_types" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5334,7 +5334,7 @@ dependencies = [ [[package]] name = "re_memory" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "backtrace", @@ -5369,7 +5369,7 @@ dependencies = [ [[package]] name = "re_query" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5400,7 +5400,7 @@ dependencies = [ [[package]] name = "re_renderer" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5453,7 +5453,7 @@ dependencies = [ [[package]] name = "re_renderer_examples" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5477,7 +5477,7 @@ dependencies = [ [[package]] name = "re_sdk" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "crossbeam", @@ -5511,7 +5511,7 @@ dependencies = [ [[package]] name = "re_sdk_comms" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "crossbeam", @@ -5527,7 +5527,7 @@ dependencies = [ [[package]] name = "re_selection_panel" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "egui_tiles", @@ -5557,7 +5557,7 @@ dependencies = [ [[package]] name = "re_smart_channel" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "crossbeam", "parking_lot", @@ -5568,7 +5568,7 @@ dependencies = [ [[package]] name = "re_space_view" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "bytemuck", "egui", @@ -5588,7 +5588,7 @@ dependencies = [ [[package]] name = "re_space_view_bar_chart" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "egui_plot", @@ -5606,7 +5606,7 @@ dependencies = [ [[package]] name = "re_space_view_dataframe" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "egui", @@ -5629,7 +5629,7 @@ dependencies = [ [[package]] name = "re_space_view_spatial" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -5668,7 +5668,7 @@ dependencies = [ [[package]] name = "re_space_view_tensor" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "bytemuck", @@ -5692,7 +5692,7 @@ dependencies = [ [[package]] name = "re_space_view_text_document" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "egui_commonmark", @@ -5707,7 +5707,7 @@ dependencies = [ [[package]] name = "re_space_view_text_log" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "egui_extras", @@ -5727,7 +5727,7 @@ dependencies = [ [[package]] name = "re_space_view_time_series" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "egui", "egui_plot", @@ -5749,7 +5749,7 @@ dependencies = [ [[package]] name = "re_string_interner" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "nohash-hasher", @@ -5761,7 +5761,7 @@ dependencies = [ [[package]] name = "re_time_panel" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "criterion", @@ -5786,7 +5786,7 @@ dependencies = [ [[package]] name = "re_tracing" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "puffin", "puffin_http", @@ -5796,7 +5796,7 @@ dependencies = [ [[package]] name = "re_tuid" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "criterion", "document-features", @@ -5808,7 +5808,7 @@ dependencies = [ [[package]] name = "re_types" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "array-init", @@ -5848,7 +5848,7 @@ dependencies = [ [[package]] name = "re_types_blueprint" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "once_cell", "re_arrow2", @@ -5859,7 +5859,7 @@ dependencies = [ [[package]] name = "re_types_builder" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "camino", @@ -5886,7 +5886,7 @@ dependencies = [ [[package]] name = "re_types_core" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "backtrace", @@ -5909,7 +5909,7 @@ dependencies = [ [[package]] name = "re_ui" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "eframe", "egui", @@ -5933,7 +5933,7 @@ dependencies = [ [[package]] name = "re_video" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "crossbeam", "econtext", @@ -5950,7 +5950,7 @@ dependencies = [ [[package]] name = "re_viewer" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -6023,7 +6023,7 @@ dependencies = [ [[package]] name = "re_viewer_context" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "anyhow", @@ -6075,7 +6075,7 @@ dependencies = [ [[package]] name = "re_viewport" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "egui", @@ -6101,7 +6101,7 @@ dependencies = [ [[package]] name = "re_viewport_blueprint" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "egui", @@ -6128,7 +6128,7 @@ dependencies = [ [[package]] name = "re_web_viewer_server" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "document-features", "re_analytics", @@ -6139,7 +6139,7 @@ dependencies = [ [[package]] name = "re_ws_comms" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "bincode", @@ -6232,7 +6232,7 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" [[package]] name = "rerun" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6271,7 +6271,7 @@ dependencies = [ [[package]] name = "rerun-cli" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "document-features", "mimalloc", @@ -6285,7 +6285,7 @@ dependencies = [ [[package]] name = "rerun-loader-rust-file" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "argh", @@ -6294,7 +6294,7 @@ dependencies = [ [[package]] name = "rerun_c" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "ahash", "infer", @@ -6308,7 +6308,7 @@ dependencies = [ [[package]] name = "rerun_py" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "arrow", "crossbeam", @@ -6412,7 +6412,7 @@ dependencies = [ [[package]] name = "roundtrip_annotation_context" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6422,7 +6422,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows2d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6432,7 +6432,7 @@ dependencies = [ [[package]] name = "roundtrip_arrows3d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6442,7 +6442,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes2d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6452,7 +6452,7 @@ dependencies = [ [[package]] name = "roundtrip_boxes3d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6462,7 +6462,7 @@ dependencies = [ [[package]] name = "roundtrip_depth_image" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6473,7 +6473,7 @@ dependencies = [ [[package]] name = "roundtrip_disconnected_space" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6483,7 +6483,7 @@ dependencies = [ [[package]] name = "roundtrip_image" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6496,7 +6496,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips2d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6506,7 +6506,7 @@ dependencies = [ [[package]] name = "roundtrip_line_strips3d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6516,7 +6516,7 @@ dependencies = [ [[package]] name = "roundtrip_pinhole" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6526,7 +6526,7 @@ dependencies = [ [[package]] name = "roundtrip_points2d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6536,7 +6536,7 @@ dependencies = [ [[package]] name = "roundtrip_points3d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6546,7 +6546,7 @@ dependencies = [ [[package]] name = "roundtrip_segmentation_image" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6557,7 +6557,7 @@ dependencies = [ [[package]] name = "roundtrip_tensor" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6568,7 +6568,7 @@ dependencies = [ [[package]] name = "roundtrip_text_document" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6578,7 +6578,7 @@ dependencies = [ [[package]] name = "roundtrip_text_log" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6588,7 +6588,7 @@ dependencies = [ [[package]] name = "roundtrip_transform3d" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6598,7 +6598,7 @@ dependencies = [ [[package]] name = "roundtrip_view_coordinates" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6608,7 +6608,7 @@ dependencies = [ [[package]] name = "roundtrip_visible_time_ranges" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -6624,7 +6624,7 @@ checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f" [[package]] name = "run_wasm" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "cargo-run-wasm", "pico-args", @@ -6905,7 +6905,7 @@ dependencies = [ [[package]] name = "shared_recording" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "rerun", ] @@ -7041,7 +7041,7 @@ dependencies = [ [[package]] name = "snippets" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "itertools 0.13.0", "ndarray 0.16.1", @@ -7064,7 +7064,7 @@ dependencies = [ [[package]] name = "spawn_viewer" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "rerun", ] @@ -7098,7 +7098,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stdio" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "rerun", ] @@ -7194,7 +7194,7 @@ dependencies = [ [[package]] name = "template" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "rerun", ] @@ -7210,7 +7210,7 @@ dependencies = [ [[package]] name = "test_api" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -7225,7 +7225,7 @@ dependencies = [ [[package]] name = "test_data_density_graph" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "rand", @@ -7235,7 +7235,7 @@ dependencies = [ [[package]] name = "test_image_memory" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "mimalloc", "re_format", @@ -7244,7 +7244,7 @@ dependencies = [ [[package]] name = "test_pinhole_projection" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", @@ -7255,7 +7255,7 @@ dependencies = [ [[package]] name = "test_send_columns" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "re_chunk", "rerun", @@ -7263,7 +7263,7 @@ dependencies = [ [[package]] name = "test_ui_wakeup" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index ff5e14fad56a..95963b894fa7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ include = ["../../LICENSE-APACHE", "../../LICENSE-MIT", "**/*.rs", "Cargo.toml"] license = "MIT OR Apache-2.0" repository = "https://github.com/rerun-io/rerun" rust-version = "1.79" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" [workspace.dependencies] # When using alpha-release, always use exact version, e.g. `version = "=0.x.y-alpha.z" @@ -34,73 +34,73 @@ version = "0.19.0-alpha.2" # 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.19.0-alpha.2", default-features = false } -re_build_tools = { path = "crates/build/re_build_tools", version = "=0.19.0-alpha.2", default-features = false } -re_dev_tools = { path = "crates/build/re_dev_tools", version = "=0.19.0-alpha.2", default-features = false } -re_types_builder = { path = "crates/build/re_types_builder", version = "=0.19.0-alpha.2", default-features = false } +re_build_info = { path = "crates/build/re_build_info", version = "=0.19.0-alpha.3", default-features = false } +re_build_tools = { path = "crates/build/re_build_tools", version = "=0.19.0-alpha.3", default-features = false } +re_dev_tools = { path = "crates/build/re_dev_tools", version = "=0.19.0-alpha.3", default-features = false } +re_types_builder = { path = "crates/build/re_types_builder", version = "=0.19.0-alpha.3", default-features = false } # crates/store: -re_chunk = { path = "crates/store/re_chunk", version = "=0.19.0-alpha.2", default-features = false } -re_chunk_store = { path = "crates/store/re_chunk_store", version = "=0.19.0-alpha.2", default-features = false } -re_data_loader = { path = "crates/store/re_data_loader", version = "=0.19.0-alpha.2", default-features = false } -re_data_source = { path = "crates/store/re_data_source", version = "=0.19.0-alpha.2", default-features = false } -re_dataframe = { path = "crates/store/re_dataframe", version = "=0.19.0-alpha.2", default-features = false } -re_entity_db = { path = "crates/store/re_entity_db", version = "=0.19.0-alpha.2", default-features = false } -re_format_arrow = { path = "crates/store/re_format_arrow", version = "=0.19.0-alpha.2", default-features = false } -re_log_encoding = { path = "crates/store/re_log_encoding", version = "=0.19.0-alpha.2", default-features = false } -re_log_types = { path = "crates/store/re_log_types", version = "=0.19.0-alpha.2", default-features = false } -re_query = { path = "crates/store/re_query", version = "=0.19.0-alpha.2", default-features = false } -re_sdk_comms = { path = "crates/store/re_sdk_comms", version = "=0.19.0-alpha.2", default-features = false } -re_types = { path = "crates/store/re_types", version = "=0.19.0-alpha.2", default-features = false } -re_types_blueprint = { path = "crates/store/re_types_blueprint", version = "=0.19.0-alpha.2", default-features = false } -re_types_core = { path = "crates/store/re_types_core", version = "=0.19.0-alpha.2", default-features = false } -re_video = { path = "crates/store/re_video", version = "=0.19.0-alpha.2", default-features = false } -re_ws_comms = { path = "crates/store/re_ws_comms", version = "=0.19.0-alpha.2", default-features = false } +re_chunk = { path = "crates/store/re_chunk", version = "=0.19.0-alpha.3", default-features = false } +re_chunk_store = { path = "crates/store/re_chunk_store", version = "=0.19.0-alpha.3", default-features = false } +re_data_loader = { path = "crates/store/re_data_loader", version = "=0.19.0-alpha.3", default-features = false } +re_data_source = { path = "crates/store/re_data_source", version = "=0.19.0-alpha.3", default-features = false } +re_dataframe = { path = "crates/store/re_dataframe", version = "=0.19.0-alpha.3", default-features = false } +re_entity_db = { path = "crates/store/re_entity_db", version = "=0.19.0-alpha.3", default-features = false } +re_format_arrow = { path = "crates/store/re_format_arrow", version = "=0.19.0-alpha.3", default-features = false } +re_log_encoding = { path = "crates/store/re_log_encoding", version = "=0.19.0-alpha.3", default-features = false } +re_log_types = { path = "crates/store/re_log_types", version = "=0.19.0-alpha.3", default-features = false } +re_query = { path = "crates/store/re_query", version = "=0.19.0-alpha.3", default-features = false } +re_sdk_comms = { path = "crates/store/re_sdk_comms", version = "=0.19.0-alpha.3", default-features = false } +re_types = { path = "crates/store/re_types", version = "=0.19.0-alpha.3", default-features = false } +re_types_blueprint = { path = "crates/store/re_types_blueprint", version = "=0.19.0-alpha.3", default-features = false } +re_types_core = { path = "crates/store/re_types_core", version = "=0.19.0-alpha.3", default-features = false } +re_video = { path = "crates/store/re_video", version = "=0.19.0-alpha.3", default-features = false } +re_ws_comms = { path = "crates/store/re_ws_comms", version = "=0.19.0-alpha.3", default-features = false } # crates/top: -re_sdk = { path = "crates/top/re_sdk", version = "=0.19.0-alpha.2", default-features = false } -rerun = { path = "crates/top/rerun", version = "=0.19.0-alpha.2", default-features = false } -rerun_c = { path = "crates/top/rerun_c", version = "=0.19.0-alpha.2", default-features = false } -rerun-cli = { path = "crates/top/rerun-cli", version = "=0.19.0-alpha.2", default-features = false } +re_sdk = { path = "crates/top/re_sdk", version = "=0.19.0-alpha.3", default-features = false } +rerun = { path = "crates/top/rerun", version = "=0.19.0-alpha.3", default-features = false } +rerun_c = { path = "crates/top/rerun_c", version = "=0.19.0-alpha.3", default-features = false } +rerun-cli = { path = "crates/top/rerun-cli", version = "=0.19.0-alpha.3", default-features = false } # crates/utils: -re_analytics = { path = "crates/utils/re_analytics", version = "=0.19.0-alpha.2", default-features = false } -re_case = { path = "crates/utils/re_case", version = "=0.19.0-alpha.2", default-features = false } -re_crash_handler = { path = "crates/utils/re_crash_handler", version = "=0.19.0-alpha.2", default-features = false } -re_error = { path = "crates/utils/re_error", version = "=0.19.0-alpha.2", default-features = false } -re_format = { path = "crates/utils/re_format", version = "=0.19.0-alpha.2", default-features = false } -re_int_histogram = { path = "crates/utils/re_int_histogram", version = "=0.19.0-alpha.2", default-features = false } -re_log = { path = "crates/utils/re_log", version = "=0.19.0-alpha.2", default-features = false } -re_memory = { path = "crates/utils/re_memory", version = "=0.19.0-alpha.2", default-features = false } -re_smart_channel = { path = "crates/utils/re_smart_channel", version = "=0.19.0-alpha.2", default-features = false } -re_string_interner = { path = "crates/utils/re_string_interner", version = "=0.19.0-alpha.2", default-features = false } -re_tracing = { path = "crates/utils/re_tracing", version = "=0.19.0-alpha.2", default-features = false } -re_tuid = { path = "crates/utils/re_tuid", version = "=0.19.0-alpha.2", default-features = false } +re_analytics = { path = "crates/utils/re_analytics", version = "=0.19.0-alpha.3", default-features = false } +re_case = { path = "crates/utils/re_case", version = "=0.19.0-alpha.3", default-features = false } +re_crash_handler = { path = "crates/utils/re_crash_handler", version = "=0.19.0-alpha.3", default-features = false } +re_error = { path = "crates/utils/re_error", version = "=0.19.0-alpha.3", default-features = false } +re_format = { path = "crates/utils/re_format", version = "=0.19.0-alpha.3", default-features = false } +re_int_histogram = { path = "crates/utils/re_int_histogram", version = "=0.19.0-alpha.3", default-features = false } +re_log = { path = "crates/utils/re_log", version = "=0.19.0-alpha.3", default-features = false } +re_memory = { path = "crates/utils/re_memory", version = "=0.19.0-alpha.3", default-features = false } +re_smart_channel = { path = "crates/utils/re_smart_channel", version = "=0.19.0-alpha.3", default-features = false } +re_string_interner = { path = "crates/utils/re_string_interner", version = "=0.19.0-alpha.3", default-features = false } +re_tracing = { path = "crates/utils/re_tracing", version = "=0.19.0-alpha.3", default-features = false } +re_tuid = { path = "crates/utils/re_tuid", version = "=0.19.0-alpha.3", default-features = false } # crates/viewer: -re_blueprint_tree = { path = "crates/viewer/re_blueprint_tree", version = "=0.19.0-alpha.2", default-features = false } -re_component_ui = { path = "crates/viewer/re_component_ui", version = "=0.19.0-alpha.2", default-features = false } -re_context_menu = { path = "crates/viewer/re_context_menu", version = "=0.19.0-alpha.2", default-features = false } -re_data_ui = { path = "crates/viewer/re_data_ui", version = "=0.19.0-alpha.2", default-features = false } -re_chunk_store_ui = { path = "crates/viewer/re_chunk_store_ui", version = "=0.19.0-alpha.2", default-features = false } -re_renderer = { path = "crates/viewer/re_renderer", version = "=0.19.0-alpha.2", default-features = false } -re_renderer_examples = { path = "crates/viewer/re_renderer_examples", version = "=0.19.0-alpha.2", default-features = false } -re_selection_panel = { path = "crates/viewer/re_selection_panel", version = "=0.19.0-alpha.2", default-features = false } -re_space_view = { path = "crates/viewer/re_space_view", version = "=0.19.0-alpha.2", default-features = false } -re_space_view_bar_chart = { path = "crates/viewer/re_space_view_bar_chart", version = "=0.19.0-alpha.2", default-features = false } -re_space_view_dataframe = { path = "crates/viewer/re_space_view_dataframe", version = "=0.19.0-alpha.2", default-features = false } -re_space_view_spatial = { path = "crates/viewer/re_space_view_spatial", version = "=0.19.0-alpha.2", default-features = false } -re_space_view_tensor = { path = "crates/viewer/re_space_view_tensor", version = "=0.19.0-alpha.2", default-features = false } -re_space_view_text_document = { path = "crates/viewer/re_space_view_text_document", version = "=0.19.0-alpha.2", default-features = false } -re_space_view_text_log = { path = "crates/viewer/re_space_view_text_log", version = "=0.19.0-alpha.2", default-features = false } -re_space_view_time_series = { path = "crates/viewer/re_space_view_time_series", version = "=0.19.0-alpha.2", default-features = false } -re_time_panel = { path = "crates/viewer/re_time_panel", version = "=0.19.0-alpha.2", default-features = false } -re_ui = { path = "crates/viewer/re_ui", version = "=0.19.0-alpha.2", default-features = false } -re_viewer = { path = "crates/viewer/re_viewer", version = "=0.19.0-alpha.2", default-features = false } -re_viewer_context = { path = "crates/viewer/re_viewer_context", version = "=0.19.0-alpha.2", default-features = false } -re_viewport = { path = "crates/viewer/re_viewport", version = "=0.19.0-alpha.2", default-features = false } -re_viewport_blueprint = { path = "crates/viewer/re_viewport_blueprint", version = "=0.19.0-alpha.2", default-features = false } -re_web_viewer_server = { path = "crates/viewer/re_web_viewer_server", version = "=0.19.0-alpha.2", default-features = false } +re_blueprint_tree = { path = "crates/viewer/re_blueprint_tree", version = "=0.19.0-alpha.3", default-features = false } +re_component_ui = { path = "crates/viewer/re_component_ui", version = "=0.19.0-alpha.3", default-features = false } +re_context_menu = { path = "crates/viewer/re_context_menu", version = "=0.19.0-alpha.3", default-features = false } +re_data_ui = { path = "crates/viewer/re_data_ui", version = "=0.19.0-alpha.3", default-features = false } +re_chunk_store_ui = { path = "crates/viewer/re_chunk_store_ui", version = "=0.19.0-alpha.3", default-features = false } +re_renderer = { path = "crates/viewer/re_renderer", version = "=0.19.0-alpha.3", default-features = false } +re_renderer_examples = { path = "crates/viewer/re_renderer_examples", version = "=0.19.0-alpha.3", default-features = false } +re_selection_panel = { path = "crates/viewer/re_selection_panel", version = "=0.19.0-alpha.3", default-features = false } +re_space_view = { path = "crates/viewer/re_space_view", version = "=0.19.0-alpha.3", default-features = false } +re_space_view_bar_chart = { path = "crates/viewer/re_space_view_bar_chart", version = "=0.19.0-alpha.3", default-features = false } +re_space_view_dataframe = { path = "crates/viewer/re_space_view_dataframe", version = "=0.19.0-alpha.3", default-features = false } +re_space_view_spatial = { path = "crates/viewer/re_space_view_spatial", version = "=0.19.0-alpha.3", default-features = false } +re_space_view_tensor = { path = "crates/viewer/re_space_view_tensor", version = "=0.19.0-alpha.3", default-features = false } +re_space_view_text_document = { path = "crates/viewer/re_space_view_text_document", version = "=0.19.0-alpha.3", default-features = false } +re_space_view_text_log = { path = "crates/viewer/re_space_view_text_log", version = "=0.19.0-alpha.3", default-features = false } +re_space_view_time_series = { path = "crates/viewer/re_space_view_time_series", version = "=0.19.0-alpha.3", default-features = false } +re_time_panel = { path = "crates/viewer/re_time_panel", version = "=0.19.0-alpha.3", default-features = false } +re_ui = { path = "crates/viewer/re_ui", version = "=0.19.0-alpha.3", default-features = false } +re_viewer = { path = "crates/viewer/re_viewer", version = "=0.19.0-alpha.3", default-features = false } +re_viewer_context = { path = "crates/viewer/re_viewer_context", version = "=0.19.0-alpha.3", default-features = false } +re_viewport = { path = "crates/viewer/re_viewport", version = "=0.19.0-alpha.3", default-features = false } +re_viewport_blueprint = { path = "crates/viewer/re_viewport_blueprint", version = "=0.19.0-alpha.3", default-features = false } +re_web_viewer_server = { path = "crates/viewer/re_web_viewer_server", version = "=0.19.0-alpha.3", default-features = false } # Rerun crates in other repos: ewebsock = "0.6.0" diff --git a/examples/rust/clock/Cargo.toml b/examples/rust/clock/Cargo.toml index 0a0923cc4de7..4335bbca1a6b 100644 --- a/examples/rust/clock/Cargo.toml +++ b/examples/rust/clock/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clock" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_data_loader/Cargo.toml b/examples/rust/custom_data_loader/Cargo.toml index f0bd49bb0f5d..a6a772b4034b 100644 --- a/examples/rust/custom_data_loader/Cargo.toml +++ b/examples/rust/custom_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_data_loader" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_space_view/Cargo.toml b/examples/rust/custom_space_view/Cargo.toml index 0773377d1a68..fe40975ce07e 100644 --- a/examples/rust/custom_space_view/Cargo.toml +++ b/examples/rust/custom_space_view/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_space_view" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/custom_store_subscriber/Cargo.toml b/examples/rust/custom_store_subscriber/Cargo.toml index eb4fc8769b16..4e5d8ccf06f7 100644 --- a/examples/rust/custom_store_subscriber/Cargo.toml +++ b/examples/rust/custom_store_subscriber/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "custom_store_subscriber" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/dna/Cargo.toml b/examples/rust/dna/Cargo.toml index 544cea3a56a1..62911054579f 100644 --- a/examples/rust/dna/Cargo.toml +++ b/examples/rust/dna/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dna" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/extend_viewer_ui/Cargo.toml b/examples/rust/extend_viewer_ui/Cargo.toml index 71ab4655860c..3449c8d7b353 100644 --- a/examples/rust/extend_viewer_ui/Cargo.toml +++ b/examples/rust/extend_viewer_ui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "extend_viewer_ui" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/external_data_loader/Cargo.toml b/examples/rust/external_data_loader/Cargo.toml index f2af2a8a681e..4a4baa4325d4 100644 --- a/examples/rust/external_data_loader/Cargo.toml +++ b/examples/rust/external_data_loader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rerun-loader-rust-file" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/incremental_logging/Cargo.toml b/examples/rust/incremental_logging/Cargo.toml index 7f9a7047202f..d17dc8e27e1e 100644 --- a/examples/rust/incremental_logging/Cargo.toml +++ b/examples/rust/incremental_logging/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "incremental_logging" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/log_file/Cargo.toml b/examples/rust/log_file/Cargo.toml index 65bbcbdf26b1..18378b908908 100644 --- a/examples/rust/log_file/Cargo.toml +++ b/examples/rust/log_file/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "log_file" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal/Cargo.toml b/examples/rust/minimal/Cargo.toml index 3f91a4322344..71fb7a62f32e 100644 --- a/examples/rust/minimal/Cargo.toml +++ b/examples/rust/minimal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_options/Cargo.toml b/examples/rust/minimal_options/Cargo.toml index 3152e86a7ce9..f030b8577bba 100644 --- a/examples/rust/minimal_options/Cargo.toml +++ b/examples/rust/minimal_options/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_options" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/minimal_serve/Cargo.toml b/examples/rust/minimal_serve/Cargo.toml index 4002f002102b..e76d76a540f6 100644 --- a/examples/rust/minimal_serve/Cargo.toml +++ b/examples/rust/minimal_serve/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "minimal_serve" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/objectron/Cargo.toml b/examples/rust/objectron/Cargo.toml index 7e0357ffb9d0..e37b06be1208 100644 --- a/examples/rust/objectron/Cargo.toml +++ b/examples/rust/objectron/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "objectron" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/raw_mesh/Cargo.toml b/examples/rust/raw_mesh/Cargo.toml index 90ad91fa6963..eaa10e98bf7a 100644 --- a/examples/rust/raw_mesh/Cargo.toml +++ b/examples/rust/raw_mesh/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "raw_mesh" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/shared_recording/Cargo.toml b/examples/rust/shared_recording/Cargo.toml index e41079128429..e7dedfd26534 100644 --- a/examples/rust/shared_recording/Cargo.toml +++ b/examples/rust/shared_recording/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shared_recording" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/spawn_viewer/Cargo.toml b/examples/rust/spawn_viewer/Cargo.toml index e75a1478dcf2..b671d98f0fb3 100644 --- a/examples/rust/spawn_viewer/Cargo.toml +++ b/examples/rust/spawn_viewer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spawn_viewer" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/stdio/Cargo.toml b/examples/rust/stdio/Cargo.toml index 698301a565ee..ad2981ebfc4f 100644 --- a/examples/rust/stdio/Cargo.toml +++ b/examples/rust/stdio/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stdio" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/examples/rust/template/Cargo.toml b/examples/rust/template/Cargo.toml index 14b9fadb2e41..14ee6dba358a 100644 --- a/examples/rust/template/Cargo.toml +++ b/examples/rust/template/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "template" -version = "0.19.0-alpha.2" +version = "0.19.0-alpha.3" edition = "2021" rust-version = "1.79" license = "MIT OR Apache-2.0" diff --git a/pixi.lock b/pixi.lock index 158f14e6ffd4..57d2b3c99cc4 100644 --- a/pixi.lock +++ b/pixi.lock @@ -12108,8 +12108,8 @@ packages: - kind: pypi name: argon2-cffi-bindings version: 21.2.0 - url: https://files.pythonhosted.org/packages/37/2c/e34e47c7dee97ba6f01a6203e0383e15b60fb85d78ac9a15cd066f6fe28b/argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl - sha256: b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f + url: https://files.pythonhosted.org/packages/5a/e4/bf8034d25edaa495da3c8a3405627d2e35758e44ff6eaa7948092646fdcc/argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl + sha256: e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93 requires_dist: - cffi>=1.0.1 - pytest ; extra == 'dev' @@ -12121,8 +12121,8 @@ packages: - kind: pypi name: argon2-cffi-bindings version: 21.2.0 - url: https://files.pythonhosted.org/packages/5a/e4/bf8034d25edaa495da3c8a3405627d2e35758e44ff6eaa7948092646fdcc/argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl - sha256: e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93 + url: https://files.pythonhosted.org/packages/37/2c/e34e47c7dee97ba6f01a6203e0383e15b60fb85d78ac9a15cd066f6fe28b/argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl + sha256: b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f requires_dist: - cffi>=1.0.1 - pytest ; extra == 'dev' @@ -12134,8 +12134,8 @@ packages: - kind: pypi name: argon2-cffi-bindings version: 21.2.0 - url: https://files.pythonhosted.org/packages/b3/02/f7f7bb6b6af6031edb11037639c697b912e1dea2db94d436e681aea2f495/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d + url: https://files.pythonhosted.org/packages/ec/f7/378254e6dd7ae6f31fe40c8649eea7d4832a42243acaf0f1fff9083b2bed/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae requires_dist: - cffi>=1.0.1 - pytest ; extra == 'dev' @@ -12147,8 +12147,8 @@ packages: - kind: pypi name: argon2-cffi-bindings version: 21.2.0 - url: https://files.pythonhosted.org/packages/ec/f7/378254e6dd7ae6f31fe40c8649eea7d4832a42243acaf0f1fff9083b2bed/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae + url: https://files.pythonhosted.org/packages/b3/02/f7f7bb6b6af6031edb11037639c697b912e1dea2db94d436e681aea2f495/argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d requires_dist: - cffi>=1.0.1 - pytest ; extra == 'dev' @@ -14741,8 +14741,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/74/ce/e8eec1a77edbfa982bee3b5460dcdd4fe0e4e3165fc15d8ec44d04da7776/black-24.4.2-cp311-cp311-win_amd64.whl - sha256: 7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 + url: https://files.pythonhosted.org/packages/9b/f7/591d601c3046ceb65b97291dfe87fa25124cffac3d97aaaba89d0f0d7bdf/black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14761,8 +14761,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/9b/f7/591d601c3046ceb65b97291dfe87fa25124cffac3d97aaaba89d0f0d7bdf/black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474 + url: https://files.pythonhosted.org/packages/74/ce/e8eec1a77edbfa982bee3b5460dcdd4fe0e4e3165fc15d8ec44d04da7776/black-24.4.2-cp311-cp311-win_amd64.whl + sha256: 7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1 requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14781,8 +14781,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl - sha256: d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c + url: https://files.pythonhosted.org/packages/c9/17/5e0036b265bbf6bc44970d93d48febcbc03701b671db3c9603fd43ebc616/black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14801,8 +14801,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/c9/17/5e0036b265bbf6bc44970d93d48febcbc03701b671db3c9603fd43ebc616/black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c + url: https://files.pythonhosted.org/packages/c5/48/34176b522e8cff4620a5d96c2e323ff2413f574870eb25efa8025885e028/black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -14821,8 +14821,8 @@ packages: - kind: pypi name: black version: 24.4.2 - url: https://files.pythonhosted.org/packages/c5/48/34176b522e8cff4620a5d96c2e323ff2413f574870eb25efa8025885e028/black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb + url: https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl + sha256: d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c requires_dist: - click>=8.0.0 - mypy-extensions>=0.4.3 @@ -15527,72 +15527,72 @@ packages: - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 + url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 + url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/95/c8/ce05a6cba2bec12d4b28285e66c53cc88dd7385b102dea7231da3b74cfef/cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404 + url: https://files.pythonhosted.org/packages/18/6c/0406611f3d5aadf4c5b08f6c095d874aed8dfc2d3a19892707d72536d5dc/cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl - sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba + url: https://files.pythonhosted.org/packages/b5/23/ea84dd4985649fcc179ba3a6c9390412e924d20b0244dc71a6545788f5a2/cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936 requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: cffi version: 1.16.0 - url: https://files.pythonhosted.org/packages/9b/89/a31c81e36bbb793581d8bba4406a8aac4ba84b2559301c44eef81f4cf5df/cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e + url: https://files.pythonhosted.org/packages/5a/c7/694814b3757878b29da39bc2f0cf9d20295f4c1e0a0bde7971708d5f23f8/cffi-1.16.0-cp311-cp311-win_amd64.whl + sha256: db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba requires_dist: - pycparser requires_python: '>=3.8' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e + url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f + url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/3e/33/21a875a61057165e92227466e54ee076b73af1e21fe1b31f1e292251aa1e/charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 + url: https://files.pythonhosted.org/packages/dd/51/68b61b90b24ca35495956b718f35a9756ef7d3dd4b3c1508056fa98d1a1b/charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl - sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 + url: https://files.pythonhosted.org/packages/e4/a6/7ee57823d46331ddc37dd00749c95b0edec2c79b15fc0d6e6efb532e89ac/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f requires_python: '>=3.7.0' - kind: pypi name: charset-normalizer version: 3.3.2 - url: https://files.pythonhosted.org/packages/40/26/f35951c45070edc957ba40a5b1db3cf60a9dbb1b350c2d5bef03e01e61de/charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 + url: https://files.pythonhosted.org/packages/57/ec/80c8d48ac8b1741d5b963797b7c0c869335619e13d4744ca2f67fc11c6fc/charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl + sha256: 663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 requires_python: '>=3.7.0' - kind: conda name: clang @@ -17194,8 +17194,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl - sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 + url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17218,8 +17218,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/33/0e/51ff72fac17e2500baf30b6b2a24be423a8d27e1625e5de99f585b852d74/contourpy-1.2.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6022cecf8f44e36af10bd9118ca71f371078b4c168b6e0fab43d4a889985dbb5 + url: https://files.pythonhosted.org/packages/d6/4f/76d0dd0bca417691918484c26c74dd9dd44fbf528bbfeb30d754886e2c54/contourpy-1.2.1-cp311-cp311-win_amd64.whl + sha256: 2855c8b0b55958265e8b5888d6a615ba02883b225f2227461aa9127c578a4922 requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17242,8 +17242,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/98/72/ae1e8518a2fe75980598a2716e392c7642b70b6a5605fc925426007b0f49/contourpy-1.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6150ffa5c767bc6332df27157d95442c379b7dce3a38dff89c0f39b63275696f + url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17266,8 +17266,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/9f/6b/8a1ca4b81d426c104fe42b3cfad9488eaaef0a03fcf98eaecc22b628a013/contourpy-1.2.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: ef5adb9a3b1d0c645ff694f9bca7702ec2c70f4d734f9922ea34de02294fdf72 + url: https://files.pythonhosted.org/packages/ee/c0/9bd123d676eb61750e116a2cd915b06483fc406143cfc36c7f263f0f5368/contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17290,8 +17290,8 @@ packages: - kind: pypi name: contourpy version: 1.2.1 - url: https://files.pythonhosted.org/packages/ee/c0/9bd123d676eb61750e116a2cd915b06483fc406143cfc36c7f263f0f5368/contourpy-1.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d4492d82b3bc7fbb7e3610747b159869468079fe149ec5c4d771fa1f614a14df + url: https://files.pythonhosted.org/packages/98/72/ae1e8518a2fe75980598a2716e392c7642b70b6a5605fc925426007b0f49/contourpy-1.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6150ffa5c767bc6332df27157d95442c379b7dce3a38dff89c0f39b63275696f requires_dist: - numpy>=1.20 - furo ; extra == 'docs' @@ -17330,8 +17330,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl - sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 + url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl + sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17358,8 +17358,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl - sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b + url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl + sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17386,8 +17386,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/52/1b/49ebc2b59e9126f1f378ae910e98704d54a3f48b78e2d6d6c8cfe6fbe06f/cryptography-38.0.4-cp36-abi3-macosx_10_10_x86_64.whl - sha256: 1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb + url: https://files.pythonhosted.org/packages/75/7a/2ea7dd2202638cf1053aaa8fbbaddded0b78c78832b3d03cafa0416a6c84/cryptography-38.0.4-cp36-abi3-macosx_10_10_universal2.whl + sha256: 2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70 requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17414,8 +17414,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl - sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d + url: https://files.pythonhosted.org/packages/a2/8f/6c52b1f9d650863e8f67edbe062c04f1c8455579eaace1593d8fe469319a/cryptography-38.0.4-cp36-abi3-manylinux_2_28_aarch64.whl + sha256: bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17442,8 +17442,8 @@ packages: - kind: pypi name: cryptography version: 38.0.4 - url: https://files.pythonhosted.org/packages/26/f8/a81170a816679fca9ccd907b801992acfc03c33f952440421c921af2cc57/cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl - sha256: ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c + url: https://files.pythonhosted.org/packages/c0/eb/f52b165db2abd662cda0a76efb7579a291fed1a7979cf41146cdc19e0d7a/cryptography-38.0.4-cp36-abi3-win_amd64.whl + sha256: 8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d requires_dist: - cffi>=1.12 - sphinx!=1.8.0,!=3.1.0,!=3.1.1,>=1.6.5 ; extra == 'docs' @@ -17643,12 +17643,6 @@ packages: purls: [] size: 618596 timestamp: 1640112124844 -- kind: pypi - name: debugpy - version: 1.8.2 - url: https://files.pythonhosted.org/packages/23/b1/3fc28ba2921234e3fad4a421dcb3185c38066eab0f92702c0d88ce891381/debugpy-1.8.2-cp311-cp311-win_amd64.whl - sha256: d3408fddd76414034c02880e891ea434e9a9cf3a69842098ef92f6e809d09afa - requires_python: '>=3.8' - kind: pypi name: debugpy version: 1.8.2 @@ -17658,8 +17652,8 @@ packages: - kind: pypi name: debugpy version: 1.8.2 - url: https://files.pythonhosted.org/packages/b4/32/dd0707c8557f99496811763c5333ea87bcec1eb233c1efa324c9a8082bff/debugpy-1.8.2-py2.py3-none-any.whl - sha256: 16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca + url: https://files.pythonhosted.org/packages/23/b1/3fc28ba2921234e3fad4a421dcb3185c38066eab0f92702c0d88ce891381/debugpy-1.8.2-cp311-cp311-win_amd64.whl + sha256: d3408fddd76414034c02880e891ea434e9a9cf3a69842098ef92f6e809d09afa requires_python: '>=3.8' - kind: pypi name: debugpy @@ -17667,6 +17661,12 @@ packages: url: https://files.pythonhosted.org/packages/4f/d6/04ae52227ab7c1d43b729d5ae75ebd592df56c55d4e4dfa30ba173096b0f/debugpy-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: acdf39855f65c48ac9667b2801234fc64d46778021efac2de7e50907ab90c634 requires_python: '>=3.8' +- kind: pypi + name: debugpy + version: 1.8.2 + url: https://files.pythonhosted.org/packages/b4/32/dd0707c8557f99496811763c5333ea87bcec1eb233c1efa324c9a8082bff/debugpy-1.8.2-py2.py3-none-any.whl + sha256: 16e16df3a98a35c63c3ab1e4d19be4cbc7fdda92d9ddc059294f18910928e0ca + requires_python: '>=3.8' - kind: pypi name: decorator version: 5.1.1 @@ -18715,8 +18715,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/c8/e1/059700c154bd7170d1c37061239836d2e51ff608f47075450f06dd3c292a/fonttools-4.53.1-cp311-cp311-win_amd64.whl - sha256: d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02 + url: https://files.pythonhosted.org/packages/8b/6a/206391c869ab22d1374e2575cad7cab36b93b9e3d37f48f4696eed2c6e9e/fonttools-4.53.1-cp311-cp311-macosx_10_9_universal2.whl + sha256: da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18752,8 +18752,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/8b/6a/206391c869ab22d1374e2575cad7cab36b93b9e3d37f48f4696eed2c6e9e/fonttools-4.53.1-cp311-cp311-macosx_10_9_universal2.whl - sha256: da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1 + url: https://files.pythonhosted.org/packages/c8/e1/059700c154bd7170d1c37061239836d2e51ff608f47075450f06dd3c292a/fonttools-4.53.1-cp311-cp311-win_amd64.whl + sha256: d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18789,8 +18789,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/e1/67/fff766817e17d67208f8a1e72de15066149485acb5e4ff0816b11fd5fca3/fonttools-4.53.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719 + url: https://files.pythonhosted.org/packages/f5/7e/4060d88dbfaf446e1c9f0fe9cf13dba36ba47c4da85ce5c1df084ce47e7d/fonttools-4.53.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: 5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18826,8 +18826,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/f5/7e/4060d88dbfaf446e1c9f0fe9cf13dba36ba47c4da85ce5c1df084ce47e7d/fonttools-4.53.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: 5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923 + url: https://files.pythonhosted.org/packages/a4/22/0a0ad59d9367997fd74a00ad2e88d10559122e09f105e94d34c155aecc0a/fonttools-4.53.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -18863,8 +18863,8 @@ packages: - kind: pypi name: fonttools version: 4.53.1 - url: https://files.pythonhosted.org/packages/a4/22/0a0ad59d9367997fd74a00ad2e88d10559122e09f105e94d34c155aecc0a/fonttools-4.53.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3 + url: https://files.pythonhosted.org/packages/e1/67/fff766817e17d67208f8a1e72de15066149485acb5e4ff0816b11fd5fca3/fonttools-4.53.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719 requires_dist: - fs<3,>=2.2.0 ; extra == 'all' - lxml>=4.0 ; extra == 'all' @@ -19054,12 +19054,6 @@ packages: purls: [] size: 642092 timestamp: 1694617858496 -- kind: pypi - name: freetype-py - version: 2.4.0 - url: https://files.pythonhosted.org/packages/b4/f5/4b8bb492464247236bd3dabd7734b3ea49adc63cf2e53160e830ebccb39d/freetype_py-2.4.0-py3-none-win_amd64.whl - sha256: a2620788d4f0c00bd75fee2dfca61635ab0da856131598c96e2355d5257f70e5 - requires_python: '>=3.7' - kind: pypi name: freetype-py version: 2.4.0 @@ -19069,8 +19063,8 @@ packages: - kind: pypi name: freetype-py version: 2.4.0 - url: https://files.pythonhosted.org/packages/85/45/f0200e64029aa0474ba4dc3e325d32c023c6607d6d8e5bc278aa27c570d3/freetype_py-2.4.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c9a3abc277f5f6d21575c0093c0c6139c161bf05b91aa6258505ab27c5001c5e + url: https://files.pythonhosted.org/packages/b4/f5/4b8bb492464247236bd3dabd7734b3ea49adc63cf2e53160e830ebccb39d/freetype_py-2.4.0-py3-none-win_amd64.whl + sha256: a2620788d4f0c00bd75fee2dfca61635ab0da856131598c96e2355d5257f70e5 requires_python: '>=3.7' - kind: pypi name: freetype-py @@ -19078,6 +19072,12 @@ packages: url: https://files.pythonhosted.org/packages/5f/34/76cfe866e482745ea8c9956b0be6198fd72d08d2be77b71596afdb8cd89f/freetype_py-2.4.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl sha256: ce931f581d5038c4fea1f3d314254e0264e92441a5fdaef6817fe77b7bb888d3 requires_python: '>=3.7' +- kind: pypi + name: freetype-py + version: 2.4.0 + url: https://files.pythonhosted.org/packages/85/45/f0200e64029aa0474ba4dc3e325d32c023c6607d6d8e5bc278aa27c570d3/freetype_py-2.4.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c9a3abc277f5f6d21575c0093c0c6139c161bf05b91aa6258505ab27c5001c5e + requires_python: '>=3.7' - kind: conda name: fribidi version: 1.0.10 @@ -20021,40 +20021,40 @@ packages: - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl - sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 + url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 + url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/41/3f/8141b03ad127fc569c3efda2bfe31d64665e02e2b8b7fbf7b25ea914c27a/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298 + url: https://files.pythonhosted.org/packages/69/0f/7f89ae2b22c55273110a44a7ed55a2948bc213fb58983093fbefcdfd2d13/google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl + sha256: cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl - sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 + url: https://files.pythonhosted.org/packages/fc/76/3ef124b893aa280e45e95d2346160f1d1d5c0ffc89d3f6e446c83116fb91/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' - kind: pypi name: google-crc32c version: 1.5.0 - url: https://files.pythonhosted.org/packages/72/92/2a2fa23db7d0b0382accbdf09768c28f7c07fc8c354cdcf2f44a47f4314e/google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906 + url: https://files.pythonhosted.org/packages/ce/8b/02bf4765c487901c8660290ade9929d65a6151c367ba32e75d136ef2d0eb/google_crc32c-1.5.0-cp311-cp311-win_amd64.whl + sha256: ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968 requires_dist: - pytest ; extra == 'testing' requires_python: '>=3.7' @@ -22341,14 +22341,6 @@ packages: purls: [] size: 86227 timestamp: 1717164911259 -- kind: pypi - name: kiwisolver - version: 1.4.5 - url: https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl - sha256: 6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355 - requires_dist: - - typing-extensions ; python_version < '3.8' - requires_python: '>=3.7' - kind: pypi name: kiwisolver version: 1.4.5 @@ -22360,8 +22352,8 @@ packages: - kind: pypi name: kiwisolver version: 1.4.5 - url: https://files.pythonhosted.org/packages/8d/26/b4569d1f29751fca22ee915b4ebfef5974f4ef239b3335fc072882bd62d9/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437 + url: https://files.pythonhosted.org/packages/1e/37/d3c2d4ba2719059a0f12730947bbe1ad5ee8bff89e8c35319dcb2c9ddb4c/kiwisolver-1.4.5-cp311-cp311-win_amd64.whl + sha256: 6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355 requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' @@ -22381,6 +22373,14 @@ packages: requires_dist: - typing-extensions ; python_version < '3.8' requires_python: '>=3.7' +- kind: pypi + name: kiwisolver + version: 1.4.5 + url: https://files.pythonhosted.org/packages/8d/26/b4569d1f29751fca22ee915b4ebfef5974f4ef239b3335fc072882bd62d9/kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437 + requires_dist: + - typing-extensions ; python_version < '3.8' + requires_python: '>=3.7' - kind: conda name: krb5 version: 1.21.3 @@ -32040,12 +32040,6 @@ packages: purls: [] size: 22221159 timestamp: 1701379965425 -- kind: pypi - name: llvmlite - version: 0.43.0 - url: https://files.pythonhosted.org/packages/20/ab/ed5ed3688c6ba4f0b8d789da19fd8e30a9cf7fc5852effe311bc5aefe73e/llvmlite-0.43.0-cp311-cp311-win_amd64.whl - sha256: d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91 - requires_python: '>=3.9' - kind: pypi name: llvmlite version: 0.43.0 @@ -32055,8 +32049,8 @@ packages: - kind: pypi name: llvmlite version: 0.43.0 - url: https://files.pythonhosted.org/packages/2f/b2/4429433eb2dc8379e2cb582502dca074c23837f8fd009907f78a24de4c25/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2 + url: https://files.pythonhosted.org/packages/20/ab/ed5ed3688c6ba4f0b8d789da19fd8e30a9cf7fc5852effe311bc5aefe73e/llvmlite-0.43.0-cp311-cp311-win_amd64.whl + sha256: d5bd550001d26450bd90777736c69d68c487d17bf371438f975229b2b8241a91 requires_python: '>=3.9' - kind: pypi name: llvmlite @@ -32070,6 +32064,12 @@ packages: url: https://files.pythonhosted.org/packages/6b/99/5d00a7d671b1ba1751fc9f19d3b36f3300774c6eebe2bcdb5f6191763eb4/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 977525a1e5f4059316b183fb4fd34fa858c9eade31f165427a3977c95e3ee749 requires_python: '>=3.9' +- kind: pypi + name: llvmlite + version: 0.43.0 + url: https://files.pythonhosted.org/packages/2f/b2/4429433eb2dc8379e2cb582502dca074c23837f8fd009907f78a24de4c25/llvmlite-0.43.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: c1da416ab53e4f7f3bc8d4eeba36d801cc1894b9fbfbf2022b29b6bad34a7df2 + requires_python: '>=3.9' - kind: pypi name: log-file version: 0.1.0 @@ -32081,8 +32081,8 @@ packages: - kind: pypi name: lxml version: 5.2.2 - url: https://files.pythonhosted.org/packages/04/19/d6aa2d980f220a04c91d4de538d2fea1a65535e7b0a4aec0998ce46e3667/lxml-5.2.2-cp311-cp311-win_amd64.whl - sha256: 49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be + url: https://files.pythonhosted.org/packages/4e/42/3bfe92749715c819763d2205370ecc7f586b44e277f38839e27cce7d6bb8/lxml-5.2.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -32093,8 +32093,8 @@ packages: - kind: pypi name: lxml version: 5.2.2 - url: https://files.pythonhosted.org/packages/4e/42/3bfe92749715c819763d2205370ecc7f586b44e277f38839e27cce7d6bb8/lxml-5.2.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88 + url: https://files.pythonhosted.org/packages/04/19/d6aa2d980f220a04c91d4de538d2fea1a65535e7b0a4aec0998ce46e3667/lxml-5.2.2-cp311-cp311-win_amd64.whl + sha256: 49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -32105,8 +32105,8 @@ packages: - kind: pypi name: lxml version: 5.2.2 - url: https://files.pythonhosted.org/packages/4e/56/c35969591789763657eb16c2fa79c924823b97da5536da8b89e11582da89/lxml-5.2.2-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: 2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3 + url: https://files.pythonhosted.org/packages/da/6a/24e9f77d17668dd4ac0a6c2a56113fd3e0db07cee51e3a67afcd47c597e5/lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl + sha256: 45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -32117,8 +32117,8 @@ packages: - kind: pypi name: lxml version: 5.2.2 - url: https://files.pythonhosted.org/packages/da/6a/24e9f77d17668dd4ac0a6c2a56113fd3e0db07cee51e3a67afcd47c597e5/lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl - sha256: 45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545 + url: https://files.pythonhosted.org/packages/ad/b7/0dc82afed00c4c189cfd0b83464f9a431c66de8e73d911063956a147276a/lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -32129,8 +32129,8 @@ packages: - kind: pypi name: lxml version: 5.2.2 - url: https://files.pythonhosted.org/packages/ad/b7/0dc82afed00c4c189cfd0b83464f9a431c66de8e73d911063956a147276a/lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5 + url: https://files.pythonhosted.org/packages/4e/56/c35969591789763657eb16c2fa79c924823b97da5536da8b89e11582da89/lxml-5.2.2-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: 2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3 requires_dist: - cssselect>=0.7 ; extra == 'cssselect' - html5lib ; extra == 'html5' @@ -32334,32 +32334,32 @@ packages: - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced + url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl - sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 + url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl + sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 + url: https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl - sha256: 629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f + url: https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 requires_python: '>=3.7' - kind: pypi name: markupsafe version: 2.1.5 - url: https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 + url: https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl + sha256: 2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 requires_python: '>=3.7' - kind: conda name: markupsafe @@ -32484,8 +32484,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/c3/2b/1c9e695967edb54f0cfb1ea5d41f5482344cf245489f8a47aa427825f264/matplotlib-3.9.1.post1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 4b49fee26d64aefa9f061b575f0f7b5fc4663e51f87375c7239efa3d30d908fa + url: https://files.pythonhosted.org/packages/a5/8b/90fae9c1b34ef3252003c26b15e8cb26b83701e34e5acf6430919c2c5c89/matplotlib-3.9.1.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 89eb7e89e2b57856533c5c98f018aa3254fa3789fcd86d5f80077b9034a54c9a requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32506,8 +32506,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/0a/d4/c0812c410de88e8646727a7c000741331875ae556018725ae169d206f0a2/matplotlib-3.9.1.post1-cp311-cp311-win_amd64.whl - sha256: c44edab5b849e0fc1f1c9d6e13eaa35ef65925f7be45be891d9784709ad95561 + url: https://files.pythonhosted.org/packages/43/ef/3fadf6545a0c609c7720477b2bfa2e578f99c106e3bd1aaf591e006c3434/matplotlib-3.9.1.post1-cp311-cp311-macosx_11_0_arm64.whl + sha256: 22b344e84fcc574f561b5731f89a7625db8ef80cdbb0026a8ea855a33e3429d1 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32528,8 +32528,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/41/dc/1f51d34daebbfe172b78fa5b5be467554b973ef30b80ed2f6200b34d3223/matplotlib-3.9.1.post1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: b08b46058fe2a31ecb81ef6aa3611f41d871f6a8280e9057cb4016cb3d8e894a + url: https://files.pythonhosted.org/packages/c3/2b/1c9e695967edb54f0cfb1ea5d41f5482344cf245489f8a47aa427825f264/matplotlib-3.9.1.post1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 4b49fee26d64aefa9f061b575f0f7b5fc4663e51f87375c7239efa3d30d908fa requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32550,8 +32550,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/43/ef/3fadf6545a0c609c7720477b2bfa2e578f99c106e3bd1aaf591e006c3434/matplotlib-3.9.1.post1-cp311-cp311-macosx_11_0_arm64.whl - sha256: 22b344e84fcc574f561b5731f89a7625db8ef80cdbb0026a8ea855a33e3429d1 + url: https://files.pythonhosted.org/packages/41/dc/1f51d34daebbfe172b78fa5b5be467554b973ef30b80ed2f6200b34d3223/matplotlib-3.9.1.post1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: b08b46058fe2a31ecb81ef6aa3611f41d871f6a8280e9057cb4016cb3d8e894a requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32572,8 +32572,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.1.post1 - url: https://files.pythonhosted.org/packages/a5/8b/90fae9c1b34ef3252003c26b15e8cb26b83701e34e5acf6430919c2c5c89/matplotlib-3.9.1.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 89eb7e89e2b57856533c5c98f018aa3254fa3789fcd86d5f80077b9034a54c9a + url: https://files.pythonhosted.org/packages/0a/d4/c0812c410de88e8646727a7c000741331875ae556018725ae169d206f0a2/matplotlib-3.9.1.post1-cp311-cp311-win_amd64.whl + sha256: c44edab5b849e0fc1f1c9d6e13eaa35ef65925f7be45be891d9784709ad95561 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32594,8 +32594,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/8b/ce/15b0bb2fb29b3d46211d8ca740b96b5232499fc49200b58b8d571292c9a6/matplotlib-3.9.2-cp311-cp311-win_amd64.whl - sha256: ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7 + url: https://files.pythonhosted.org/packages/77/c2/f9d7fe80a8fcce9bb128d1381c6fe41a8d286d7e18395e273002e8e0fa34/matplotlib-3.9.2-cp311-cp311-macosx_10_12_x86_64.whl + sha256: d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32616,8 +32616,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/77/c2/f9d7fe80a8fcce9bb128d1381c6fe41a8d286d7e18395e273002e8e0fa34/matplotlib-3.9.2-cp311-cp311-macosx_10_12_x86_64.whl - sha256: d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772 + url: https://files.pythonhosted.org/packages/8b/ce/15b0bb2fb29b3d46211d8ca740b96b5232499fc49200b58b8d571292c9a6/matplotlib-3.9.2-cp311-cp311-win_amd64.whl + sha256: ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32638,8 +32638,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/e6/9a/5991972a560db3ab621312a7ca5efec339ae2122f25901c0846865c4b72f/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f + url: https://files.pythonhosted.org/packages/28/ba/8be09886eb56ac04a218a1dc3fa728a5c4cac60b019b4f1687885166da00/matplotlib-3.9.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32660,8 +32660,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/28/ba/8be09886eb56ac04a218a1dc3fa728a5c4cac60b019b4f1687885166da00/matplotlib-3.9.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41 + url: https://files.pythonhosted.org/packages/01/75/6c7ce560e95714a10fcbb3367d1304975a1a3e620f72af28921b796403f3/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447 requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -32682,8 +32682,8 @@ packages: - kind: pypi name: matplotlib version: 3.9.2 - url: https://files.pythonhosted.org/packages/01/75/6c7ce560e95714a10fcbb3367d1304975a1a3e620f72af28921b796403f3/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447 + url: https://files.pythonhosted.org/packages/e6/9a/5991972a560db3ab621312a7ca5efec339ae2122f25901c0846865c4b72f/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f requires_dist: - contourpy>=1.0.1 - cycler>=0.10 @@ -33041,32 +33041,32 @@ packages: - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/3f/e1/7fdd0f39565df3af87d6c2903fb66a7d529fbd0a8a066045d7a5b6ad1145/multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3 + url: https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl - sha256: 2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea + url: https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: 612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e + url: https://files.pythonhosted.org/packages/3f/e1/7fdd0f39565df3af87d6c2903fb66a7d529fbd0a8a066045d7a5b6ad1145/multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3 requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/02/c1/b15ecceb6ffa5081ed2ed450aea58d65b0e0358001f2b426705f9f41f4c2/multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: 612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd + url: https://files.pythonhosted.org/packages/21/db/3403263f158b0bc7b0d4653766d71cb39498973f2042eead27b2e9758782/multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e requires_python: '>=3.7' - kind: pypi name: multidict version: 6.0.5 - url: https://files.pythonhosted.org/packages/52/ec/be54a3ad110f386d5bd7a9a42a4ff36b3cd723ebe597f41073a73ffa16b8/multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed + url: https://files.pythonhosted.org/packages/88/aa/ea217cb18325aa05cb3e3111c19715f1e97c50a4a900cbc20e54648de5f5/multidict-6.0.5-cp311-cp311-win_amd64.whl + sha256: 2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea requires_python: '>=3.7' - kind: conda name: multidict @@ -34038,8 +34038,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/79/89/2d924ca60dbf949f18a6fec223a2445f5f428d9a5f97a6b29c2122319015/numba-0.60.0-cp311-cp311-win_amd64.whl - sha256: cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2 + url: https://files.pythonhosted.org/packages/98/ad/df18d492a8f00d29a30db307904b9b296e37507034eedb523876f3a2e13e/numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34047,8 +34047,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/98/ad/df18d492a8f00d29a30db307904b9b296e37507034eedb523876f3a2e13e/numba-0.60.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: a17b70fc9e380ee29c42717e8cc0bfaa5556c416d94f9aa96ba13acb41bdece8 + url: https://files.pythonhosted.org/packages/79/89/2d924ca60dbf949f18a6fec223a2445f5f428d9a5f97a6b29c2122319015/numba-0.60.0-cp311-cp311-win_amd64.whl + sha256: cac02c041e9b5bc8cf8f2034ff6f0dbafccd1ae9590dc146b3a02a45e53af4e2 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34056,8 +34056,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/f9/4c/8889ac94c0b33dca80bed11564b8c6d9ea14d7f094e674c58e5c5b05859b/numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl - sha256: 5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703 + url: https://files.pythonhosted.org/packages/9a/51/a4dc2c01ce7a850b8e56ff6d5381d047a5daea83d12bad08aa071d34b2ee/numba-0.60.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 3fb02b344a2a80efa6f677aa5c40cd5dd452e1b35f8d1c2af0dfd9ada9978e4b requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34065,8 +34065,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/9a/51/a4dc2c01ce7a850b8e56ff6d5381d047a5daea83d12bad08aa071d34b2ee/numba-0.60.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 3fb02b344a2a80efa6f677aa5c40cd5dd452e1b35f8d1c2af0dfd9ada9978e4b + url: https://files.pythonhosted.org/packages/57/03/2b4245b05b71c0cee667e6a0b51606dfa7f4157c9093d71c6b208385a611/numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl + sha256: 4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34074,8 +34074,8 @@ packages: - kind: pypi name: numba version: 0.60.0 - url: https://files.pythonhosted.org/packages/57/03/2b4245b05b71c0cee667e6a0b51606dfa7f4157c9093d71c6b208385a611/numba-0.60.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - sha256: 4142d7ac0210cc86432b818338a2bc368dc773a2f5cf1e32ff7c5b378bd63ee8 + url: https://files.pythonhosted.org/packages/f9/4c/8889ac94c0b33dca80bed11564b8c6d9ea14d7f094e674c58e5c5b05859b/numba-0.60.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl + sha256: 5f4fde652ea604ea3c86508a3fb31556a6157b2c76c8b51b1d45eb40c8598703 requires_dist: - llvmlite<0.44,>=0.43.0.dev0 - numpy<2.1,>=1.22 @@ -34466,8 +34466,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/a7/9e/7110d2c5d543ab03b9581dbb1f8e2429863e44e0c9b4960b766f230c1279/opencv_contrib_python-4.10.0.84-cp37-abi3-win_amd64.whl - sha256: 47ec3160dae75f70e099b286d1a2e086d20dac8b06e759f60eaf867e6bdecba7 + url: https://files.pythonhosted.org/packages/09/94/d077c4c976c2d7a88812fd55396e92edae0e0c708689dbd8c8f508920e47/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl + sha256: dea80d4db73b8acccf9e16b5744bf3654f47b22745074263f0a6c10de26c5ef5 requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -34483,8 +34483,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/09/94/d077c4c976c2d7a88812fd55396e92edae0e0c708689dbd8c8f508920e47/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl - sha256: dea80d4db73b8acccf9e16b5744bf3654f47b22745074263f0a6c10de26c5ef5 + url: https://files.pythonhosted.org/packages/a7/9e/7110d2c5d543ab03b9581dbb1f8e2429863e44e0c9b4960b766f230c1279/opencv_contrib_python-4.10.0.84-cp37-abi3-win_amd64.whl + sha256: 47ec3160dae75f70e099b286d1a2e086d20dac8b06e759f60eaf867e6bdecba7 requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -34500,8 +34500,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/f8/76/f76fe74b864f3cfa737173ca12e8890aad8369e980006fb8a0b6cd14c6c7/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 040575b69e4f3aa761676bace4e3d1b8485fbfaf77ef77b266ab6bda5a3b5e9b + url: https://files.pythonhosted.org/packages/92/64/c1194510eaed272d86b53a08c790ca6ed1c450f06d401c49c8145fc46d40/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_11_0_arm64.whl + sha256: ee4b0919026d8c533aeb69b16c6ec4a891a2f6844efaa14121bf68838753209c requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -34517,8 +34517,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/92/64/c1194510eaed272d86b53a08c790ca6ed1c450f06d401c49c8145fc46d40/opencv_contrib_python-4.10.0.84-cp37-abi3-macosx_11_0_arm64.whl - sha256: ee4b0919026d8c533aeb69b16c6ec4a891a2f6844efaa14121bf68838753209c + url: https://files.pythonhosted.org/packages/b0/e0/8f5d065ebb2e5941d289c5f653f944318f9e418bc5167bc6a346ab5e0f6a/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a261223db41f6e512d76deaf21c8fcfb4fbbcbc2de62ca7f74a05f2c9ee489ef requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -34534,8 +34534,8 @@ packages: - kind: pypi name: opencv-contrib-python version: 4.10.0.84 - url: https://files.pythonhosted.org/packages/b0/e0/8f5d065ebb2e5941d289c5f653f944318f9e418bc5167bc6a346ab5e0f6a/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: a261223db41f6e512d76deaf21c8fcfb4fbbcbc2de62ca7f74a05f2c9ee489ef + url: https://files.pythonhosted.org/packages/f8/76/f76fe74b864f3cfa737173ca12e8890aad8369e980006fb8a0b6cd14c6c7/opencv_contrib_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 040575b69e4f3aa761676bace4e3d1b8485fbfaf77ef77b266ab6bda5a3b5e9b requires_dist: - numpy>=1.13.3 ; python_version < '3.7' - numpy>=1.21.0 ; python_version <= '3.9' and platform_system == 'Darwin' and platform_machine == 'arm64' @@ -35050,8 +35050,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl - sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 + url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -35142,8 +35142,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/1b/70/61704497903d43043e288017cb2b82155c0d41e15f5c17807920877b45c2/pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288 + url: https://files.pythonhosted.org/packages/ab/63/966db1321a0ad55df1d1fe51505d2cdae191b84c907974873817b0a6e849/pandas-2.2.2-cp311-cp311-win_amd64.whl + sha256: 873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24 requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -35234,8 +35234,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/97/2d/7b54f80b93379ff94afb3bd9b0cd1d17b48183a0d6f98045bc01ce1e06a7/pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b + url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -35326,8 +35326,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/16/c6/75231fd47afd6b3f89011e7077f1a3958441264aca7ae9ff596e3276a5d0/pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: 8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151 + url: https://files.pythonhosted.org/packages/fc/a5/4d82be566f069d7a9a702dcdf6f9106df0e0b042e738043c0cc7ddd7e3f6/pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -35418,8 +35418,8 @@ packages: - kind: pypi name: pandas version: 2.2.2 - url: https://files.pythonhosted.org/packages/fc/a5/4d82be566f069d7a9a702dcdf6f9106df0e0b042e738043c0cc7ddd7e3f6/pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee + url: https://files.pythonhosted.org/packages/97/2d/7b54f80b93379ff94afb3bd9b0cd1d17b48183a0d6f98045bc01ce1e06a7/pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b requires_dist: - numpy>=1.22.4 ; python_version < '3.11' - numpy>=1.23.2 ; python_version == '3.11' @@ -35685,8 +35685,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f + url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35709,8 +35709,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd + url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35733,8 +35733,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/7a/54/f6a14d95cba8ff082c550d836c9e5c23f1641d2ac291c23efe0494219b8c/Pillow-10.0.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 9fb218c8a12e51d7ead2a7c9e101a04982237d4855716af2e9499306728fb485 + url: https://files.pythonhosted.org/packages/b7/ad/71982d18fd28ed1f93c31b8648f980ebdbdbcf7d8c9c9b4af59290914ce9/Pillow-10.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: d35e3c8d9b1268cbf5d3670285feb3528f6680420eafe35cccc686b73c1e330f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35757,8 +35757,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl - sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f + url: https://files.pythonhosted.org/packages/79/53/3a7277ae95bfe86b8b4db0ed1d08c4924aa2dfbfe51b8fe0e310b160a9c6/Pillow-10.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: c1fbe7621c167ecaa38ad29643d77a9ce7311583761abf7836e1510c580bf3dd requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35781,8 +35781,8 @@ packages: - kind: pypi name: pillow version: 10.0.0 - url: https://files.pythonhosted.org/packages/16/89/818fa238e37a47a29bb8495ca2cafdd514599a89f19ada7916348a74b5f9/Pillow-10.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: cd25d2a9d2b36fcb318882481367956d2cf91329f6892fe5d385c346c0649629 + url: https://files.pythonhosted.org/packages/66/d4/054e491f0880bf0119ee79cdc03264e01d5732e06c454da8c69b83a7c8f2/Pillow-10.0.0-cp311-cp311-win_amd64.whl + sha256: 3a82c40d706d9aa9734289740ce26460a11aeec2d9c79b7af87bb35f0073c12f requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35805,8 +35805,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe + url: https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: 76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35832,8 +35832,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl - sha256: cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91 + url: https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35859,8 +35859,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl - sha256: 0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c + url: https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35886,8 +35886,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be + url: https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl + sha256: 0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -35913,8 +35913,8 @@ packages: - kind: pypi name: pillow version: 10.4.0 - url: https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: 76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319 + url: https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl + sha256: cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91 requires_dist: - furo ; extra == 'docs' - olefile ; extra == 'docs' @@ -36202,26 +36202,26 @@ packages: - kind: pypi name: protobuf version: 5.27.2 - url: https://files.pythonhosted.org/packages/cd/c7/a534268f9c3780be1ba50f5ed96243fa9cf6224a445de662c34e91ce0e61/protobuf-5.27.2-cp38-abi3-manylinux2014_aarch64.whl - sha256: 176c12b1f1c880bf7a76d9f7c75822b6a2bc3db2d28baa4d300e8ce4cde7409b + url: https://files.pythonhosted.org/packages/27/e4/8dc4546be46873f8950cb44cdfe19b79d66d26e53c4ee5e3440406257fcd/protobuf-5.27.2-cp38-abi3-manylinux2014_x86_64.whl + sha256: b848dbe1d57ed7c191dfc4ea64b8b004a3f9ece4bf4d0d80a367b76df20bf36e requires_python: '>=3.8' - kind: pypi name: protobuf version: 5.27.2 - url: https://files.pythonhosted.org/packages/b1/04/73b8fd7f34f3a2b2b64aa31a173b8aebbdb0c55523df4c027846bb44bc1e/protobuf-5.27.2-cp310-abi3-win_amd64.whl - sha256: 0e341109c609749d501986b835f667c6e1e24531096cff9d34ae411595e26505 + url: https://files.pythonhosted.org/packages/cd/c7/a534268f9c3780be1ba50f5ed96243fa9cf6224a445de662c34e91ce0e61/protobuf-5.27.2-cp38-abi3-manylinux2014_aarch64.whl + sha256: 176c12b1f1c880bf7a76d9f7c75822b6a2bc3db2d28baa4d300e8ce4cde7409b requires_python: '>=3.8' - kind: pypi name: protobuf version: 5.27.2 - url: https://files.pythonhosted.org/packages/27/e4/8dc4546be46873f8950cb44cdfe19b79d66d26e53c4ee5e3440406257fcd/protobuf-5.27.2-cp38-abi3-manylinux2014_x86_64.whl - sha256: b848dbe1d57ed7c191dfc4ea64b8b004a3f9ece4bf4d0d80a367b76df20bf36e + url: https://files.pythonhosted.org/packages/b1/04/73b8fd7f34f3a2b2b64aa31a173b8aebbdb0c55523df4c027846bb44bc1e/protobuf-5.27.2-cp310-abi3-win_amd64.whl + sha256: 0e341109c609749d501986b835f667c6e1e24531096cff9d34ae411595e26505 requires_python: '>=3.8' - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132 + url: https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -36232,8 +36232,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl - sha256: 33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3 + url: https://files.pythonhosted.org/packages/7c/06/63872a64c312a24fb9b4af123ee7007a306617da63ff13bcc1432386ead7/psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl + sha256: ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -36244,8 +36244,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl - sha256: c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0 + url: https://files.pythonhosted.org/packages/cd/5f/60038e277ff0a9cc8f0c9ea3d0c5eb6ee1d2470ea3f9389d776432888e47/psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -36256,8 +36256,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/7c/06/63872a64c312a24fb9b4af123ee7007a306617da63ff13bcc1432386ead7/psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl - sha256: ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0 + url: https://files.pythonhosted.org/packages/0b/37/f8da2fbd29690b3557cca414c1949f92162981920699cd62095a984983bf/psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl + sha256: c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -36268,8 +36268,8 @@ packages: - kind: pypi name: psutil version: 6.0.0 - url: https://files.pythonhosted.org/packages/19/74/f59e7e0d392bc1070e9a70e2f9190d652487ac115bb16e2eff6b22ad1d24/psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd + url: https://files.pythonhosted.org/packages/73/44/561092313ae925f3acfaace6f9ddc4f6a9c748704317bad9c8c8f8a36a79/psutil-6.0.0-cp37-abi3-win_amd64.whl + sha256: 33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3 requires_dist: - ipaddress ; python_version < '3.0' and extra == 'test' - mock ; python_version < '3.0' and extra == 'test' @@ -36374,8 +36374,8 @@ packages: - kind: pypi name: psygnal version: 0.11.1 - url: https://files.pythonhosted.org/packages/25/92/6dcab17c3bb91fa3f250ebdbb66de55332436da836c4c547c26e3942877e/psygnal-0.11.1-cp311-cp311-macosx_10_16_x86_64.whl - sha256: 8f77317cbd11fbed5bfdd40ea41b4e551ee0cf37881cdbc325b67322af577485 + url: https://files.pythonhosted.org/packages/68/76/d5c5bf5a932ec2dcdc4a23565815a1cc5fd96b03b26ff3f647cdff5ea62c/psygnal-0.11.1-py3-none-any.whl + sha256: 04255fe28828060a80320f8fda937c47bc0c21ca14f55a13eb7c494b165ea395 requires_dist: - ipython ; extra == 'dev' - mypy ; extra == 'dev' @@ -36411,8 +36411,8 @@ packages: - kind: pypi name: psygnal version: 0.11.1 - url: https://files.pythonhosted.org/packages/68/76/d5c5bf5a932ec2dcdc4a23565815a1cc5fd96b03b26ff3f647cdff5ea62c/psygnal-0.11.1-py3-none-any.whl - sha256: 04255fe28828060a80320f8fda937c47bc0c21ca14f55a13eb7c494b165ea395 + url: https://files.pythonhosted.org/packages/25/92/6dcab17c3bb91fa3f250ebdbb66de55332436da836c4c547c26e3942877e/psygnal-0.11.1-cp311-cp311-macosx_10_16_x86_64.whl + sha256: 8f77317cbd11fbed5bfdd40ea41b4e551ee0cf37881cdbc325b67322af577485 requires_dist: - ipython ; extra == 'dev' - mypy ; extra == 'dev' @@ -36748,8 +36748,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/f9/46/ce89f87c2936f5bb9d879473b9663ce7a4b1f4359acc2f0eb39865eaa1af/pyarrow-17.0.0-cp311-cp311-macosx_10_15_x86_64.whl - sha256: 1c8856e2ef09eb87ecf937104aacfa0708f22dfeb039c363ec99735190ffb977 + url: https://files.pythonhosted.org/packages/d8/81/69b6606093363f55a2a574c018901c40952d4e902e670656d18213c71ad7/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_aarch64.whl + sha256: dc5c31c37409dfbc5d014047817cb4ccd8c1ea25d19576acf1a001fe07f5b420 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -36761,8 +36761,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/8d/8e/ce2e9b2146de422f6638333c01903140e9ada244a2a477918a368306c64c/pyarrow-17.0.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 2e19f569567efcbbd42084e87f948778eb371d308e137a0f97afe19bb860ccb3 + url: https://files.pythonhosted.org/packages/30/d1/63a7c248432c71c7d3ee803e706590a0b81ce1a8d2b2ae49677774b813bb/pyarrow-17.0.0-cp311-cp311-win_amd64.whl + sha256: a27532c38f3de9eb3e90ecab63dfda948a8ca859a66e3a47f5f42d1e403c4d03 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -36774,8 +36774,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/30/d1/63a7c248432c71c7d3ee803e706590a0b81ce1a8d2b2ae49677774b813bb/pyarrow-17.0.0-cp311-cp311-win_amd64.whl - sha256: a27532c38f3de9eb3e90ecab63dfda948a8ca859a66e3a47f5f42d1e403c4d03 + url: https://files.pythonhosted.org/packages/4c/21/9ca93b84b92ef927814cb7ba37f0774a484c849d58f0b692b16af8eebcfb/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: e3343cb1e88bc2ea605986d4b94948716edc7a8d14afd4e2c097232f729758b4 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -36787,8 +36787,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/4c/21/9ca93b84b92ef927814cb7ba37f0774a484c849d58f0b692b16af8eebcfb/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: e3343cb1e88bc2ea605986d4b94948716edc7a8d14afd4e2c097232f729758b4 + url: https://files.pythonhosted.org/packages/f9/46/ce89f87c2936f5bb9d879473b9663ce7a4b1f4359acc2f0eb39865eaa1af/pyarrow-17.0.0-cp311-cp311-macosx_10_15_x86_64.whl + sha256: 1c8856e2ef09eb87ecf937104aacfa0708f22dfeb039c363ec99735190ffb977 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -36800,8 +36800,8 @@ packages: - kind: pypi name: pyarrow version: 17.0.0 - url: https://files.pythonhosted.org/packages/d8/81/69b6606093363f55a2a574c018901c40952d4e902e670656d18213c71ad7/pyarrow-17.0.0-cp311-cp311-manylinux_2_28_aarch64.whl - sha256: dc5c31c37409dfbc5d014047817cb4ccd8c1ea25d19576acf1a001fe07f5b420 + url: https://files.pythonhosted.org/packages/8d/8e/ce2e9b2146de422f6638333c01903140e9ada244a2a477918a368306c64c/pyarrow-17.0.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 2e19f569567efcbbd42084e87f948778eb371d308e137a0f97afe19bb860ccb3 requires_dist: - numpy>=1.16.6 - pytest ; extra == 'test' @@ -37165,8 +37165,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/2e/f5/dfa78dc72e47dfe1ada7b37fedcb338454750470358a6dfcfdfda35fa337/pycocotools-2.0.8-cp311-cp311-win_amd64.whl - sha256: e680e27e58b840c105fa09a3bb1d91706038c5c8d7b7bf09c2e5ecbd1b05ad7f + url: https://files.pythonhosted.org/packages/6b/56/9eedccfd1cfdaf6553d527bed0b2b5572550567a5786a8beb098027a3e5e/pycocotools-2.0.8-cp311-cp311-macosx_10_9_universal2.whl + sha256: 92bf788e6936fc52b57ccaaa78ecdaeac81872eebbfc45b6fe16ae18b85709bd requires_dist: - matplotlib>=2.1.0 - numpy @@ -37174,8 +37174,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/6b/56/9eedccfd1cfdaf6553d527bed0b2b5572550567a5786a8beb098027a3e5e/pycocotools-2.0.8-cp311-cp311-macosx_10_9_universal2.whl - sha256: 92bf788e6936fc52b57ccaaa78ecdaeac81872eebbfc45b6fe16ae18b85709bd + url: https://files.pythonhosted.org/packages/2e/f5/dfa78dc72e47dfe1ada7b37fedcb338454750470358a6dfcfdfda35fa337/pycocotools-2.0.8-cp311-cp311-win_amd64.whl + sha256: e680e27e58b840c105fa09a3bb1d91706038c5c8d7b7bf09c2e5ecbd1b05ad7f requires_dist: - matplotlib>=2.1.0 - numpy @@ -37183,8 +37183,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/d5/9c/09cd808743338db170915deb35fa020b792d583238afe55f27c011f91c3c/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 6a07f57f991e379959c0f4a1b9ea35d875876433b7f45c6d8fe6b718e58834bc + url: https://files.pythonhosted.org/packages/8b/d4/7279d072c0255d07c541326f6058effb1b08190f49695bf2c22aae666878/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 5968a1e5421719af9eb7ccee4c540bfb18b1fc95d30d9a48571d0aaeb159a1ae requires_dist: - matplotlib>=2.1.0 - numpy @@ -37192,8 +37192,8 @@ packages: - kind: pypi name: pycocotools version: 2.0.8 - url: https://files.pythonhosted.org/packages/8b/d4/7279d072c0255d07c541326f6058effb1b08190f49695bf2c22aae666878/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 5968a1e5421719af9eb7ccee4c540bfb18b1fc95d30d9a48571d0aaeb159a1ae + url: https://files.pythonhosted.org/packages/d5/9c/09cd808743338db170915deb35fa020b792d583238afe55f27c011f91c3c/pycocotools-2.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 6a07f57f991e379959c0f4a1b9ea35d875876433b7f45c6d8fe6b718e58834bc requires_dist: - matplotlib>=2.1.0 - numpy @@ -37291,8 +37291,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl - sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 + url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl + sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d requires_dist: - cffi>=1.4.1 - sphinx>=1.6.5 ; extra == 'docs' @@ -37303,8 +37303,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl - sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 + url: https://files.pythonhosted.org/packages/59/bb/fddf10acd09637327a97ef89d2a9d621328850a72f1fdc8c08bdf72e385f/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl + sha256: 52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 requires_dist: - cffi>=1.4.1 - sphinx>=1.6.5 ; extra == 'docs' @@ -37315,8 +37315,8 @@ packages: - kind: pypi name: pynacl version: 1.5.0 - url: https://files.pythonhosted.org/packages/ee/87/f1bb6a595f14a327e8285b9eb54d41fef76c585a0edef0a45f6fc95de125/PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl - sha256: 0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d + url: https://files.pythonhosted.org/packages/5e/22/d3db169895faaf3e2eda892f005f433a62db2decbcfbc2f61e6517adfa87/PyNaCl-1.5.0-cp36-abi3-win_amd64.whl + sha256: 20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 requires_dist: - cffi>=1.4.1 - sphinx>=1.6.5 ; extra == 'docs' @@ -37367,14 +37367,6 @@ packages: - railroad-diagrams ; extra == 'diagrams' - jinja2 ; extra == 'diagrams' requires_python: '>=3.6.8' -- kind: pypi - name: pyproj - version: 3.6.0 - url: https://files.pythonhosted.org/packages/c8/5a/215a1894e50167d91b471d8fc413ca30034c48e5d3dfac78d12df4c840d5/pyproj-3.6.0-cp311-cp311-win_amd64.whl - sha256: 8fbac2eb9a0e425d7d6b7c6f4ebacd675cf3bdef0c59887057b8b4b0374e7c12 - requires_dist: - - certifi - requires_python: '>=3.9' - kind: pypi name: pyproj version: 3.6.0 @@ -37386,8 +37378,8 @@ packages: - kind: pypi name: pyproj version: 3.6.0 - url: https://files.pythonhosted.org/packages/82/ea/208144cd3fb42a3bf70630a1300c32a9dc1705b777d6c2fb1ebd1517fad5/pyproj-3.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 08dfc5c9533c78a97afae9d53b99b810a4a8f97c3be9eb2b8f323b726c736403 + url: https://files.pythonhosted.org/packages/c8/5a/215a1894e50167d91b471d8fc413ca30034c48e5d3dfac78d12df4c840d5/pyproj-3.6.0-cp311-cp311-win_amd64.whl + sha256: 8fbac2eb9a0e425d7d6b7c6f4ebacd675cf3bdef0c59887057b8b4b0374e7c12 requires_dist: - certifi requires_python: '>=3.9' @@ -37407,6 +37399,14 @@ packages: requires_dist: - certifi requires_python: '>=3.9' +- kind: pypi + name: pyproj + version: 3.6.0 + url: https://files.pythonhosted.org/packages/82/ea/208144cd3fb42a3bf70630a1300c32a9dc1705b777d6c2fb1ebd1517fad5/pyproj-3.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 08dfc5c9533c78a97afae9d53b99b810a4a8f97c3be9eb2b8f323b726c736403 + requires_dist: + - certifi + requires_python: '>=3.9' - kind: pypi name: pyquaternion version: 0.9.9 @@ -37768,12 +37768,6 @@ packages: url: https://files.pythonhosted.org/packages/02/f0/2004a0c907eb74155b6fafa5801931d9e15d55905db6811f146cc2d145cd/pywinpty-2.0.13-cp311-none-win_amd64.whl sha256: b96fb14698db1284db84ca38c79f15b4cfdc3172065b5137383910567591fa99 requires_python: '>=3.8' -- kind: pypi - name: pyyaml - version: 6.0.1 - url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl - sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 - requires_python: '>=3.6' - kind: pypi name: pyyaml version: 6.0.1 @@ -37783,8 +37777,8 @@ packages: - kind: pypi name: pyyaml version: 6.0.1 - url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d + url: https://files.pythonhosted.org/packages/b3/34/65bb4b2d7908044963ebf614fe0fdb080773fc7030d7e39c8d3eddcd4257/PyYAML-6.0.1-cp311-cp311-win_amd64.whl + sha256: bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 requires_python: '>=3.6' - kind: pypi name: pyyaml @@ -37798,35 +37792,41 @@ packages: url: https://files.pythonhosted.org/packages/7b/5e/efd033ab7199a0b2044dab3b9f7a4f6670e6a52c089de572e928d2873b06/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 requires_python: '>=3.6' +- kind: pypi + name: pyyaml + version: 6.0.1 + url: https://files.pythonhosted.org/packages/5e/94/7d5ee059dfb92ca9e62f4057dcdec9ac08a9e42679644854dc01177f8145/PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d + requires_python: '>=3.6' - kind: pypi name: pyzmq version: 26.0.3 - url: https://files.pythonhosted.org/packages/3f/11/20e8b114c197ead632bff8730593b5f249dd143ad71dfac9f639b354f309/pyzmq-26.0.3-cp311-cp311-win_amd64.whl - sha256: 3191d312c73e3cfd0f0afdf51df8405aafeb0bad71e7ed8f68b24b63c4f36500 + url: https://files.pythonhosted.org/packages/4b/60/4e5170ffdf1720791752f09261a813efd5e59ec8ccf3e909d50d62a13b7d/pyzmq-26.0.3-cp311-cp311-macosx_10_15_universal2.whl + sha256: a72a84570f84c374b4c287183debc776dc319d3e8ce6b6a0041ce2e400de3f32 requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' - kind: pypi name: pyzmq version: 26.0.3 - url: https://files.pythonhosted.org/packages/4b/60/4e5170ffdf1720791752f09261a813efd5e59ec8ccf3e909d50d62a13b7d/pyzmq-26.0.3-cp311-cp311-macosx_10_15_universal2.whl - sha256: a72a84570f84c374b4c287183debc776dc319d3e8ce6b6a0041ce2e400de3f32 + url: https://files.pythonhosted.org/packages/3f/11/20e8b114c197ead632bff8730593b5f249dd143ad71dfac9f639b354f309/pyzmq-26.0.3-cp311-cp311-win_amd64.whl + sha256: 3191d312c73e3cfd0f0afdf51df8405aafeb0bad71e7ed8f68b24b63c4f36500 requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' - kind: pypi name: pyzmq version: 26.0.3 - url: https://files.pythonhosted.org/packages/e5/b5/625e45790a1b091f54d5d47fd267d051cabdec4f01144f6b2fcb7306515b/pyzmq-26.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7 + url: https://files.pythonhosted.org/packages/9b/20/92275f936eaa612f0192f8a02b2f66564e41498216f37a760501d2591149/pyzmq-26.0.3-cp311-cp311-manylinux_2_28_x86_64.whl + sha256: ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' - kind: pypi name: pyzmq version: 26.0.3 - url: https://files.pythonhosted.org/packages/9b/20/92275f936eaa612f0192f8a02b2f66564e41498216f37a760501d2591149/pyzmq-26.0.3-cp311-cp311-manylinux_2_28_x86_64.whl - sha256: ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a + url: https://files.pythonhosted.org/packages/e5/b5/625e45790a1b091f54d5d47fd267d051cabdec4f01144f6b2fcb7306515b/pyzmq-26.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7 requires_dist: - cffi ; implementation_name == 'pypy' requires_python: '>=3.7' @@ -38251,12 +38251,6 @@ packages: - attrs>=22.2.0 - rpds-py>=0.7.0 requires_python: '>=3.8' -- kind: pypi - name: regex - version: 2024.5.15 - url: https://files.pythonhosted.org/packages/ef/9b/0aa55fc101c803869c13b389b718b15810592d2df35b1af15ff5b6f48e16/regex-2024.5.15-cp311-cp311-win_amd64.whl - sha256: 9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201 - requires_python: '>=3.8' - kind: pypi name: regex version: 2024.5.15 @@ -38266,8 +38260,8 @@ packages: - kind: pypi name: regex version: 2024.5.15 - url: https://files.pythonhosted.org/packages/7d/ba/cbbcdad38b40f1fa36eee1a130051d8e3cd2bd40d3a2a7bce4cf6ff82190/regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35 + url: https://files.pythonhosted.org/packages/ef/9b/0aa55fc101c803869c13b389b718b15810592d2df35b1af15ff5b6f48e16/regex-2024.5.15-cp311-cp311-win_amd64.whl + sha256: 9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201 requires_python: '>=3.8' - kind: pypi name: regex @@ -38281,6 +38275,12 @@ packages: url: https://files.pythonhosted.org/packages/39/29/8158a6e69e97b9c72fab0b46fe4d57c789d07ef91fe4afde23721e7cac61/regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f requires_python: '>=3.8' +- kind: pypi + name: regex + version: 2024.5.15 + url: https://files.pythonhosted.org/packages/7d/ba/cbbcdad38b40f1fa36eee1a130051d8e3cd2bd40d3a2a7bce4cf6ff82190/regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35 + requires_python: '>=3.8' - kind: pypi name: requests version: 2.32.3 @@ -38307,9 +38307,9 @@ packages: - watchfiles ; extra == 'dev' - kind: pypi name: rerun-notebook - version: 0.19.0a2 + version: 0.19.0a3 path: rerun_notebook - sha256: bd617f21c499675c3a72dfe727aade2ccde81dc7c53e76c3982f5172c3c37ecb + sha256: a161d453a8611727fae787ff6374fe6f5d538283ca1a1a78386691ae08017575 requires_dist: - anywidget - jupyter-ui-poll @@ -38320,8 +38320,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/8c/28/92423fe9673b738c180fb5b6b8ea4203fe4b02c1d20b06b7fae79d11cc24/rerun_sdk-0.17.0-cp38-abi3-win_amd64.whl - sha256: 34e5595a326cbdddfebdf00b08e877358c564fce74cc8c6d617fc89ef3a6aa70 + url: https://files.pythonhosted.org/packages/b7/c5/d47ba7b774bc563aa3c07ba500dd304ea24b31fe438e10ea9ad5e10ffe17/rerun_sdk-0.17.0-cp38-abi3-macosx_11_0_arm64.whl + sha256: 8b0a8a6feab3f8e679801d158216a71d88a81480021587719330f50d083c4d26 requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -38362,8 +38362,8 @@ packages: - kind: pypi name: rerun-sdk version: 0.17.0 - url: https://files.pythonhosted.org/packages/b7/c5/d47ba7b774bc563aa3c07ba500dd304ea24b31fe438e10ea9ad5e10ffe17/rerun_sdk-0.17.0-cp38-abi3-macosx_11_0_arm64.whl - sha256: 8b0a8a6feab3f8e679801d158216a71d88a81480021587719330f50d083c4d26 + url: https://files.pythonhosted.org/packages/8c/28/92423fe9673b738c180fb5b6b8ea4203fe4b02c1d20b06b7fae79d11cc24/rerun_sdk-0.17.0-cp38-abi3-win_amd64.whl + sha256: 34e5595a326cbdddfebdf00b08e877358c564fce74cc8c6d617fc89ef3a6aa70 requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -38389,9 +38389,9 @@ packages: requires_python: '>=3.8,<3.13' - kind: pypi name: rerun-sdk - version: 0.19.0a2 + version: 0.19.0a3 path: rerun_py - sha256: 498c80e631847223d0da7185901724fca71b55c526efc7f95e41bbf64ce42134 + sha256: e0609c08b62bca12fe232bd3f1b247778e39c994ccaf2fd95823853d231af67b requires_dist: - attrs>=23.1.0 - numpy>=1.23,<2 @@ -38399,7 +38399,7 @@ packages: - pyarrow>=14.0.2 - typing-extensions>=4.5 - pytest==7.1.2 ; extra == 'tests' - - rerun-notebook==0.19.0a2 ; extra == 'notebook' + - rerun-notebook==0.19.0a3 ; extra == 'notebook' requires_python: '>=3.8,<3.13' editable: true - kind: pypi @@ -38501,12 +38501,6 @@ packages: url: https://files.pythonhosted.org/packages/3d/5e/5593c140bf3c7b2688cc5fe1e6ebee7e486df443f9e9f6021588233c6323/rpds_py-0.19.0-cp311-cp311-macosx_11_0_arm64.whl sha256: c5c9581019c96f865483d031691a5ff1cc455feb4d84fc6920a5ffc48a794d8a requires_python: '>=3.8' -- kind: pypi - name: rpds-py - version: 0.19.1 - url: https://files.pythonhosted.org/packages/2c/98/3baa188d20f3228589bc5fc516982888d10f26769f54980facbc54150443/rpds_py-0.19.1-cp311-none-win_amd64.whl - sha256: c149a652aeac4902ecff2dd93c3b2681c608bd5208c793c4a99404b3e1afc87c - requires_python: '>=3.8' - kind: pypi name: rpds-py version: 0.19.1 @@ -38516,8 +38510,8 @@ packages: - kind: pypi name: rpds-py version: 0.19.1 - url: https://files.pythonhosted.org/packages/d0/b4/3e58dd849bbc85b51523bad48da9e1f8d09f5f791124ba0593ae6fc02f47/rpds_py-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 3837c63dd6918a24de6c526277910e3766d8c2b1627c500b155f3eecad8fad65 + url: https://files.pythonhosted.org/packages/2c/98/3baa188d20f3228589bc5fc516982888d10f26769f54980facbc54150443/rpds_py-0.19.1-cp311-none-win_amd64.whl + sha256: c149a652aeac4902ecff2dd93c3b2681c608bd5208c793c4a99404b3e1afc87c requires_python: '>=3.8' - kind: pypi name: rpds-py @@ -38525,6 +38519,12 @@ packages: url: https://files.pythonhosted.org/packages/36/b8/f269fed9aee00fbe96f24e016be76ba685794bc75d3fd30bd88953b474d0/rpds_py-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: c34f751bf67cab69638564eee34023909380ba3e0d8ee7f6fe473079bf93f09b requires_python: '>=3.8' +- kind: pypi + name: rpds-py + version: 0.19.1 + url: https://files.pythonhosted.org/packages/d0/b4/3e58dd849bbc85b51523bad48da9e1f8d09f5f791124ba0593ae6fc02f47/rpds_py-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 3837c63dd6918a24de6c526277910e3766d8c2b1627c500b155f3eecad8fad65 + requires_python: '>=3.8' - kind: pypi name: rrt-star version: 0.1.0 @@ -38677,8 +38677,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl - sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 + url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -38717,8 +38717,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/9f/d9/1bd2c06c1e7aff0c6db4affff5c0b8d6b2fa421ee0d2de94408d43e6aa7c/safetensors-0.4.3-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 22f3b5d65e440cec0de8edaa672efa888030802e11c09b3d6203bff60ebff05a + url: https://files.pythonhosted.org/packages/cb/f6/19f268662be898ff2a23ac06f8dd0d2956b2ecd204c96e1ee07ba292c119/safetensors-0.4.3-cp311-none-win_amd64.whl + sha256: 840b7ac0eff5633e1d053cc9db12fdf56b566e9403b4950b2dc85393d9b88d67 requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -38757,8 +38757,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/85/f8/13934886b30f4429a480ee24be217cefc279f1d40e1cf0250b327404ab82/safetensors-0.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e9afd5358719f1b2cf425fad638fc3c887997d6782da317096877e5b15b2ce93 + url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl + sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -38797,8 +38797,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/82/61/d4812330b32600972e92ef09a59dc54f9ab8ae570fdca28d8bdfc5577756/safetensors-0.4.3-cp311-cp311-macosx_11_0_arm64.whl - sha256: 7c4fa560ebd4522adddb71dcd25d09bf211b5634003f015a4b815b7647d62ebe + url: https://files.pythonhosted.org/packages/d5/85/1e7d2804cbf82204cde462d16f1cb0ff5814b03f559fb46ceaa6b7020db4/safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -38837,8 +38837,8 @@ packages: - kind: pypi name: safetensors version: 0.4.3 - url: https://files.pythonhosted.org/packages/d5/85/1e7d2804cbf82204cde462d16f1cb0ff5814b03f559fb46ceaa6b7020db4/safetensors-0.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 0bf4f9d6323d9f86eef5567eabd88f070691cf031d4c0df27a40d3b4aaee755b + url: https://files.pythonhosted.org/packages/85/f8/13934886b30f4429a480ee24be217cefc279f1d40e1cf0250b327404ab82/safetensors-0.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e9afd5358719f1b2cf425fad638fc3c887997d6782da317096877e5b15b2ce93 requires_dist: - numpy>=1.21.6 ; extra == 'numpy' - safetensors[numpy] ; extra == 'torch' @@ -38877,8 +38877,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/50/b2/d5e97115733e2dc657e99868ae0237705b79d0c81f6ced21b8f0799a30d1/scikit_image-0.24.0-cp311-cp311-win_amd64.whl - sha256: dacf591ac0c272a111181afad4b788a27fe70d213cfddd631d151cbc34f8ca2c + url: https://files.pythonhosted.org/packages/90/e3/564beb0c78bf83018a146dfcdc959c99c10a0d136480b932a350c852adbc/scikit_image-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 272909e02a59cea3ed4aa03739bb88df2625daa809f633f40b5053cf09241831 requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -38944,8 +38944,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/90/e3/564beb0c78bf83018a146dfcdc959c99c10a0d136480b932a350c852adbc/scikit_image-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 272909e02a59cea3ed4aa03739bb88df2625daa809f633f40b5053cf09241831 + url: https://files.pythonhosted.org/packages/50/b2/d5e97115733e2dc657e99868ae0237705b79d0c81f6ced21b8f0799a30d1/scikit_image-0.24.0-cp311-cp311-win_amd64.whl + sha256: dacf591ac0c272a111181afad4b788a27fe70d213cfddd631d151cbc34f8ca2c requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39011,8 +39011,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/b8/2e/3a949995f8fc2a65b15a4964373e26c5601cb2ea68f36b115571663e7a38/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 59c98cc695005faf2b79904e4663796c977af22586ddf1b12d6af2fa22842dc2 + url: https://files.pythonhosted.org/packages/3c/f6/be8b16d8ab6ebf19057877c2aec905cbd438dd92ca64b8efe9e9af008fa3/scikit_image-0.24.0-cp311-cp311-macosx_12_0_arm64.whl + sha256: 190ebde80b4470fe8838764b9b15f232a964f1a20391663e31008d76f0c696f7 requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39078,8 +39078,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/3c/f6/be8b16d8ab6ebf19057877c2aec905cbd438dd92ca64b8efe9e9af008fa3/scikit_image-0.24.0-cp311-cp311-macosx_12_0_arm64.whl - sha256: 190ebde80b4470fe8838764b9b15f232a964f1a20391663e31008d76f0c696f7 + url: https://files.pythonhosted.org/packages/ad/96/138484302b8ec9a69cdf65e8d4ab47a640a3b1a8ea3c437e1da3e1a5a6b8/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fa27b3a0dbad807b966b8db2d78da734cb812ca4787f7fbb143764800ce2fa9c requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39145,8 +39145,8 @@ packages: - kind: pypi name: scikit-image version: 0.24.0 - url: https://files.pythonhosted.org/packages/ad/96/138484302b8ec9a69cdf65e8d4ab47a640a3b1a8ea3c437e1da3e1a5a6b8/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fa27b3a0dbad807b966b8db2d78da734cb812ca4787f7fbb143764800ce2fa9c + url: https://files.pythonhosted.org/packages/b8/2e/3a949995f8fc2a65b15a4964373e26c5601cb2ea68f36b115571663e7a38/scikit_image-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 59c98cc695005faf2b79904e4663796c977af22586ddf1b12d6af2fa22842dc2 requires_dist: - numpy>=1.23 - scipy>=1.9 @@ -39212,8 +39212,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/5d/55/0403bf2031250ac982c8053397889fbc5a3a2b3798b913dae4f51c3af6a4/scikit_learn-1.5.1-cp311-cp311-win_amd64.whl - sha256: 9a07f90846313a7639af6a019d849ff72baadfa4c74c778821ae0fad07b7275b + url: https://files.pythonhosted.org/packages/03/86/ab9f95e338c5ef5b4e79463ee91e55aae553213835e59bf038bc0cc21bf8/scikit_learn-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 154297ee43c0b83af12464adeab378dee2d0a700ccd03979e2b821e7dd7cc1c2 requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39273,8 +39273,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/03/86/ab9f95e338c5ef5b4e79463ee91e55aae553213835e59bf038bc0cc21bf8/scikit_learn-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 154297ee43c0b83af12464adeab378dee2d0a700ccd03979e2b821e7dd7cc1c2 + url: https://files.pythonhosted.org/packages/5d/55/0403bf2031250ac982c8053397889fbc5a3a2b3798b913dae4f51c3af6a4/scikit_learn-1.5.1-cp311-cp311-win_amd64.whl + sha256: 9a07f90846313a7639af6a019d849ff72baadfa4c74c778821ae0fad07b7275b requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39334,8 +39334,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/c1/f8/fd3fa610cac686952d8c78b8b44cf5263c6c03885bd8e5d5819c684b44e8/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 909144d50f367a513cee6090873ae582dba019cb3fca063b38054fa42704c3a4 + url: https://files.pythonhosted.org/packages/7d/d7/fb80c63062b60b1fa5dcb2d4dd3a4e83bd8c68cdc83cf6ff8c016228f184/scikit_learn-1.5.1-cp311-cp311-macosx_12_0_arm64.whl + sha256: b5e865e9bd59396220de49cb4a57b17016256637c61b4c5cc81aaf16bc123bbe requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39395,8 +39395,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/7d/d7/fb80c63062b60b1fa5dcb2d4dd3a4e83bd8c68cdc83cf6ff8c016228f184/scikit_learn-1.5.1-cp311-cp311-macosx_12_0_arm64.whl - sha256: b5e865e9bd59396220de49cb4a57b17016256637c61b4c5cc81aaf16bc123bbe + url: https://files.pythonhosted.org/packages/32/63/ed228892adad313aab0d0f9261241e7bf1efe36730a2788ad424bcad00ca/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 689b6f74b2c880276e365fe84fe4f1befd6a774f016339c65655eaff12e10cbf requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39456,8 +39456,8 @@ packages: - kind: pypi name: scikit-learn version: 1.5.1 - url: https://files.pythonhosted.org/packages/32/63/ed228892adad313aab0d0f9261241e7bf1efe36730a2788ad424bcad00ca/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 689b6f74b2c880276e365fe84fe4f1befd6a774f016339c65655eaff12e10cbf + url: https://files.pythonhosted.org/packages/c1/f8/fd3fa610cac686952d8c78b8b44cf5263c6c03885bd8e5d5819c684b44e8/scikit_learn-1.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 909144d50f367a513cee6090873ae582dba019cb3fca063b38054fa42704c3a4 requires_dist: - numpy>=1.19.5 - scipy>=1.6.0 @@ -39517,8 +39517,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/91/1d/0484130df7e33e044da88a091827d6441b77f907075bf7bbe145857d6590/scipy-1.14.0-cp311-cp311-win_amd64.whl - sha256: 5b083c8940028bb7e0b4172acafda6df762da1927b9091f9611b0bcd8676f2bc + url: https://files.pythonhosted.org/packages/10/55/d6096721c0f0d7e7369da9660a854c14e6379ab7aba603ea5d492d77fa23/scipy-1.14.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 6d056a8709ccda6cf36cdd2eac597d13bc03dba38360f418560a93050c76a16e requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -39559,8 +39559,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/10/55/d6096721c0f0d7e7369da9660a854c14e6379ab7aba603ea5d492d77fa23/scipy-1.14.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 6d056a8709ccda6cf36cdd2eac597d13bc03dba38360f418560a93050c76a16e + url: https://files.pythonhosted.org/packages/91/1d/0484130df7e33e044da88a091827d6441b77f907075bf7bbe145857d6590/scipy-1.14.0-cp311-cp311-win_amd64.whl + sha256: 5b083c8940028bb7e0b4172acafda6df762da1927b9091f9611b0bcd8676f2bc requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -39601,8 +39601,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/6c/bb/f44e22697740893ffa84239ca3766bdb908c1c7135ebb272d5bd4bdc33e2/scipy-1.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 9eee2989868e274aae26125345584254d97c56194c072ed96cb433f32f692ed8 + url: https://files.pythonhosted.org/packages/56/95/1a3a04b5facab8287325ad2335dbb6b78b98d73690c832099c9c498f7a4d/scipy-1.14.0-cp311-cp311-macosx_12_0_arm64.whl + sha256: f0a50da861a7ec4573b7c716b2ebdcdf142b66b756a0d392c236ae568b3a93fb requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -39643,8 +39643,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/56/95/1a3a04b5facab8287325ad2335dbb6b78b98d73690c832099c9c498f7a4d/scipy-1.14.0-cp311-cp311-macosx_12_0_arm64.whl - sha256: f0a50da861a7ec4573b7c716b2ebdcdf142b66b756a0d392c236ae568b3a93fb + url: https://files.pythonhosted.org/packages/89/bb/80c9c98d887c855710fd31fc5ae5574133e98203b3475b07579251803662/scipy-1.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 9e3154691b9f7ed73778d746da2df67a19d046a6c8087c8b385bc4cdb2cfca74 requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -39685,8 +39685,8 @@ packages: - kind: pypi name: scipy version: 1.14.0 - url: https://files.pythonhosted.org/packages/89/bb/80c9c98d887c855710fd31fc5ae5574133e98203b3475b07579251803662/scipy-1.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 9e3154691b9f7ed73778d746da2df67a19d046a6c8087c8b385bc4cdb2cfca74 + url: https://files.pythonhosted.org/packages/6c/bb/f44e22697740893ffa84239ca3766bdb908c1c7135ebb272d5bd4bdc33e2/scipy-1.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 9eee2989868e274aae26125345584254d97c56194c072ed96cb433f32f692ed8 requires_dist: - numpy<2.3,>=1.23.5 - pytest ; extra == 'test' @@ -39958,8 +39958,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/ec/1b/092fff53cbeced411eed2717592e31cadd3e52f0ebaba5f2df3f34913f96/shapely-2.0.5-cp311-cp311-win_amd64.whl - sha256: 6c6b78c0007a34ce7144f98b7418800e0a6a5d9a762f2244b00ea560525290c9 + url: https://files.pythonhosted.org/packages/29/3d/0d3ab80860cda6afbce9736fa1f091f452092d344fdd4e3c65e5fe7b1111/shapely-2.0.5-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 5bbfb048a74cf273db9091ff3155d373020852805a37dfc846ab71dde4be93ec requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -39973,8 +39973,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/29/3d/0d3ab80860cda6afbce9736fa1f091f452092d344fdd4e3c65e5fe7b1111/shapely-2.0.5-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 5bbfb048a74cf273db9091ff3155d373020852805a37dfc846ab71dde4be93ec + url: https://files.pythonhosted.org/packages/ec/1b/092fff53cbeced411eed2717592e31cadd3e52f0ebaba5f2df3f34913f96/shapely-2.0.5-cp311-cp311-win_amd64.whl + sha256: 6c6b78c0007a34ce7144f98b7418800e0a6a5d9a762f2244b00ea560525290c9 requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -39988,8 +39988,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/7e/4e/4e83b9f3d7f0ce523c92bdf3dfe0292738d8ad2b589971390d6205bc843e/shapely-2.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 0f8e71bb9a46814019f6644c4e2560a09d44b80100e46e371578f35eaaa9da1c + url: https://files.pythonhosted.org/packages/80/68/6b51b7587547f6bbd0965cf957505a0ebec93510e840572a983003b3a0a9/shapely-2.0.5-cp311-cp311-macosx_11_0_arm64.whl + sha256: 93be600cbe2fbaa86c8eb70656369f2f7104cd231f0d6585c7d0aa555d6878b8 requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -40003,8 +40003,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/80/68/6b51b7587547f6bbd0965cf957505a0ebec93510e840572a983003b3a0a9/shapely-2.0.5-cp311-cp311-macosx_11_0_arm64.whl - sha256: 93be600cbe2fbaa86c8eb70656369f2f7104cd231f0d6585c7d0aa555d6878b8 + url: https://files.pythonhosted.org/packages/ed/a8/c8b0f1a165e161247caf0fc265d61de3c4ea27d7c313c7ebfb1c4f6ddea4/shapely-2.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d5251c28a29012e92de01d2e84f11637eb1d48184ee8f22e2df6c8c578d26760 requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -40018,8 +40018,8 @@ packages: - kind: pypi name: shapely version: 2.0.5 - url: https://files.pythonhosted.org/packages/ed/a8/c8b0f1a165e161247caf0fc265d61de3c4ea27d7c313c7ebfb1c4f6ddea4/shapely-2.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d5251c28a29012e92de01d2e84f11637eb1d48184ee8f22e2df6c8c578d26760 + url: https://files.pythonhosted.org/packages/7e/4e/4e83b9f3d7f0ce523c92bdf3dfe0292738d8ad2b589971390d6205bc843e/shapely-2.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 0f8e71bb9a46814019f6644c4e2560a09d44b80100e46e371578f35eaaa9da1c requires_dist: - numpy<3,>=1.14 - numpydoc==1.1.* ; extra == 'docs' @@ -40087,12 +40087,6 @@ packages: purls: [] size: 213817 timestamp: 1643442169866 -- kind: pypi - name: simplejson - version: 3.19.2 - url: https://files.pythonhosted.org/packages/b6/8e/3e12d122dfdf549a8d12eaf39954ee39f2027060aa38b63430f8ab3244e7/simplejson-3.19.2-cp311-cp311-win_amd64.whl - sha256: 9300aee2a8b5992d0f4293d88deb59c218989833e3396c824b69ba330d04a589 - requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson version: 3.19.2 @@ -40102,8 +40096,8 @@ packages: - kind: pypi name: simplejson version: 3.19.2 - url: https://files.pythonhosted.org/packages/a0/d8/f9e822563d5ccf9e199719a64db221f942c9a04cce17140c4b4fe51a25fc/simplejson-3.19.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: ef7938a78447174e2616be223f496ddccdbf7854f7bf2ce716dbccd958cc7d13 + url: https://files.pythonhosted.org/packages/b6/8e/3e12d122dfdf549a8d12eaf39954ee39f2027060aa38b63430f8ab3244e7/simplejson-3.19.2-cp311-cp311-win_amd64.whl + sha256: 9300aee2a8b5992d0f4293d88deb59c218989833e3396c824b69ba330d04a589 requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: simplejson @@ -40117,6 +40111,12 @@ packages: url: https://files.pythonhosted.org/packages/70/c1/816573ae91aebf06a0fefd8ea30ca43127aa58e68684d2ddfe17c8457afb/simplejson-3.19.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 4d36081c0b1c12ea0ed62c202046dca11438bee48dd5240b7c8de8da62c620e9 requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' +- kind: pypi + name: simplejson + version: 3.19.2 + url: https://files.pythonhosted.org/packages/a0/d8/f9e822563d5ccf9e199719a64db221f942c9a04cce17140c4b4fe51a25fc/simplejson-3.19.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: ef7938a78447174e2616be223f496ddccdbf7854f7bf2ce716dbccd958cc7d13 + requires_python: '>=2.5,!=3.0.*,!=3.1.*,!=3.2.*' - kind: pypi name: six version: 1.16.0 @@ -40230,8 +40230,8 @@ packages: - kind: pypi name: sounddevice version: 0.4.7 - url: https://files.pythonhosted.org/packages/d4/09/bfdd393f1bb1b90b4a6849b84972b7059c95e36818cc489922228d58cc63/sounddevice-0.4.7-py3-none-win_amd64.whl - sha256: 0c8b3543da1496f282b66a7bc54b755577ba638b1af06c146d4ac7f39d86b548 + url: https://files.pythonhosted.org/packages/1c/9c/d8de668a462b7a326d9f697dfa2adb6fbde07cc468cc7cdcf51cbe975d56/sounddevice-0.4.7-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl + sha256: d6ddfd341ad7412b14ca001f2c4dbf5fa2503bdc9eb15ad2c3105f6c260b698a requires_dist: - cffi>=1.0 - numpy ; extra == 'numpy' @@ -40239,8 +40239,8 @@ packages: - kind: pypi name: sounddevice version: 0.4.7 - url: https://files.pythonhosted.org/packages/1c/9c/d8de668a462b7a326d9f697dfa2adb6fbde07cc468cc7cdcf51cbe975d56/sounddevice-0.4.7-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl - sha256: d6ddfd341ad7412b14ca001f2c4dbf5fa2503bdc9eb15ad2c3105f6c260b698a + url: https://files.pythonhosted.org/packages/d4/09/bfdd393f1bb1b90b4a6849b84972b7059c95e36818cc489922228d58cc63/sounddevice-0.4.7-py3-none-win_amd64.whl + sha256: 0c8b3543da1496f282b66a7bc54b755577ba638b1af06c146d4ac7f39d86b548 requires_dist: - cffi>=1.0 - numpy ; extra == 'numpy' @@ -40820,8 +40820,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl - sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 + url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl + sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -40838,8 +40838,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/c8/d6/6e1d728d765eb4102767f071bf7f6439ab10d7f4a975c9217db65715207a/tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl - sha256: 5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059 + url: https://files.pythonhosted.org/packages/65/8e/6d7d72b28f22c422cff8beae10ac3c2e4376b9be721ef8167b7eecd1da62/tokenizers-0.19.1-cp311-none-win_amd64.whl + sha256: ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -40856,8 +40856,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/36/c6/537f22b57e6003904d35d07962dbde2f2e9bdd791d0241da976a4c7f8194/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc + url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl + sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -40874,8 +40874,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/90/79/d17a0f491d10817cd30f1121a07aa09c8e97a81114b116e473baf1577f09/tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl - sha256: ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14 + url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -40892,8 +40892,8 @@ packages: - kind: pypi name: tokenizers version: 0.19.1 - url: https://files.pythonhosted.org/packages/a7/03/fb50fc03f86016b227a967c8d474f90230c885c0d18f78acdfda7a96ce56/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa + url: https://files.pythonhosted.org/packages/36/c6/537f22b57e6003904d35d07962dbde2f2e9bdd791d0241da976a4c7f8194/tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc requires_dist: - huggingface-hub>=0.16.4,<1.0 - pytest ; extra == 'testing' @@ -40950,8 +40950,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl - sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 + url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf requires_dist: - filelock - typing-extensions>=4.8.0 @@ -40977,8 +40977,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/02/af/81abea3d73fddfde26afd1ce52a4ddfa389cd2b684c89d6c4d0d5d8d0dfa/torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf + url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl + sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41004,8 +41004,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl - sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 + url: https://files.pythonhosted.org/packages/3f/14/e105b8ef6d324e789c1589e95cb0ab63f3e07c2216d68b1178b7c21b7d2a/torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl + sha256: 95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059 requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41031,8 +41031,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl - sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb + url: https://files.pythonhosted.org/packages/96/23/18b9c16c18a77755e7f15173821c7100f11e6b3b7717bea8d729bdeb92c0/torch-2.2.2-cp311-none-macosx_11_0_arm64.whl + sha256: 49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1 requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41058,8 +41058,8 @@ packages: - kind: pypi name: torch version: 2.2.2 - url: https://files.pythonhosted.org/packages/5c/01/5ab75f138bf32d7a69df61e4997e24eccad87cc009f5fb7e2a31af8a4036/torch-2.2.2-cp311-cp311-win_amd64.whl - sha256: f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c + url: https://files.pythonhosted.org/packages/c3/33/d7a6123231bd4d04c7005dde8507235772f3bc4622a25f3a88c016415d49/torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl + sha256: ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb requires_dist: - filelock - typing-extensions>=4.8.0 @@ -41085,8 +41085,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl - sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 + url: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl + sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 requires_dist: - numpy - torch==2.2.2 @@ -41096,8 +41096,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/46/95/179dd1bf8fd6bd689f0907f4baed557d2b12d2cf3d7ed1a8ecefe0a63d83/torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl - sha256: 9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54 + url: https://files.pythonhosted.org/packages/c6/75/d869f600fc33df8b8ca99943e165a4ca23b73c68dc1942098fde0a6b46f3/torchvision-0.17.2-cp311-cp311-win_amd64.whl + sha256: 6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431 requires_dist: - numpy - torch==2.2.2 @@ -41107,8 +41107,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/56/8d/a153903bfd610450258ee7ac5d292d6b8f382aec14f49404845d8ba6207d/torchvision-0.17.2-cp311-cp311-manylinux2014_aarch64.whl - sha256: 833fd2e4216ced924c8aca0525733fe727f9a1af66dfad7c5be7257e97c39678 + url: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl + sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d requires_dist: - numpy - torch==2.2.2 @@ -41118,8 +41118,8 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/36/15/c48f74f8f8d382677ef016b65f09969028a1549b8a518c18894deb95b544/torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl - sha256: e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d + url: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl + sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 requires_dist: - numpy - torch==2.2.2 @@ -41129,20 +41129,14 @@ packages: - kind: pypi name: torchvision version: 0.17.2 - url: https://files.pythonhosted.org/packages/68/49/5e1c771294407bb25e6dbcf169aef5cffefcddf27b0176125a9b0af06a1e/torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl - sha256: 3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69 + url: https://files.pythonhosted.org/packages/56/8d/a153903bfd610450258ee7ac5d292d6b8f382aec14f49404845d8ba6207d/torchvision-0.17.2-cp311-cp311-manylinux2014_aarch64.whl + sha256: 833fd2e4216ced924c8aca0525733fe727f9a1af66dfad7c5be7257e97c39678 requires_dist: - numpy - torch==2.2.2 - pillow!=8.3.*,>=5.3.0 - scipy ; extra == 'scipy' requires_python: '>=3.8' -- kind: pypi - name: tornado - version: 6.4.1 - url: https://files.pythonhosted.org/packages/d9/2f/3f2f05e84a7aff787a96d5fb06821323feb370fe0baed4db6ea7b1088f32/tornado-6.4.1-cp38-abi3-win_amd64.whl - sha256: b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7 - requires_python: '>=3.8' - kind: pypi name: tornado version: 6.4.1 @@ -41152,8 +41146,8 @@ packages: - kind: pypi name: tornado version: 6.4.1 - url: https://files.pythonhosted.org/packages/13/cf/786b8f1e6fe1c7c675e79657448178ad65e41c1c9765ef82e7f6f765c4c5/tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4 + url: https://files.pythonhosted.org/packages/d9/2f/3f2f05e84a7aff787a96d5fb06821323feb370fe0baed4db6ea7b1088f32/tornado-6.4.1-cp38-abi3-win_amd64.whl + sha256: b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7 requires_python: '>=3.8' - kind: pypi name: tornado @@ -41167,6 +41161,12 @@ packages: url: https://files.pythonhosted.org/packages/22/d4/54f9d12668b58336bd30defe0307e6c61589a3e687b05c366f804b7faaf0/tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl sha256: 613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3 requires_python: '>=3.8' +- kind: pypi + name: tornado + version: 6.4.1 + url: https://files.pythonhosted.org/packages/13/cf/786b8f1e6fe1c7c675e79657448178ad65e41c1c9765ef82e7f6f765c4c5/tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4 + requires_python: '>=3.8' - kind: pypi name: tqdm version: 4.66.4 @@ -42388,32 +42388,32 @@ packages: - kind: pypi name: uv version: 0.2.26 - url: https://files.pythonhosted.org/packages/b3/2c/8d18a2e39015ad132bfa8d8ff31b8bad5cea6760db0534963d54944b13f1/uv-0.2.26-py3-none-macosx_11_0_arm64.whl - sha256: 3117aabd606cbe70a3a1589301ce14d578f3f62a46025b26e251b664b01b3728 + url: https://files.pythonhosted.org/packages/7a/30/24a74c0ca887d3a75821814d292e1001571d574c4c2b217a858b09ce8b88/uv-0.2.26-py3-none-macosx_10_12_x86_64.whl + sha256: fd3e850921f0d51d093aaeb76d190829eefdc0345439b8f6c06103a0463cc451 requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.26 - url: https://files.pythonhosted.org/packages/93/22/f39356b5519e2ff7dad7cc2a45146fd144659cae48ef5c6ce054d655b7cc/uv-0.2.26-py3-none-manylinux_2_28_aarch64.whl - sha256: c1ba6064f8bff59e3e6a7c59cf27ce4cffc6bf2eed1777134522b65c562f9206 + url: https://files.pythonhosted.org/packages/0f/b6/cbb68a3b7faf7afa406d38b6d94065f759cac1b13a0a15dffa5bf7d7b60f/uv-0.2.26-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 65120080bbd2f2ce47e92f6065e223f2f416feb3a323ea9574d3e993b7ebde9f requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.26 - url: https://files.pythonhosted.org/packages/7a/30/24a74c0ca887d3a75821814d292e1001571d574c4c2b217a858b09ce8b88/uv-0.2.26-py3-none-macosx_10_12_x86_64.whl - sha256: fd3e850921f0d51d093aaeb76d190829eefdc0345439b8f6c06103a0463cc451 + url: https://files.pythonhosted.org/packages/b3/2c/8d18a2e39015ad132bfa8d8ff31b8bad5cea6760db0534963d54944b13f1/uv-0.2.26-py3-none-macosx_11_0_arm64.whl + sha256: 3117aabd606cbe70a3a1589301ce14d578f3f62a46025b26e251b664b01b3728 requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.26 - url: https://files.pythonhosted.org/packages/ee/d1/d0311b79198f5f07809edcb6b71f38f8e8e0d848194ff0f5bfcd1cd941fe/uv-0.2.26-py3-none-win_amd64.whl - sha256: 05949e0135d5093d555f17ca6701e5939547d8a656bec003b7986e3540533348 + url: https://files.pythonhosted.org/packages/93/22/f39356b5519e2ff7dad7cc2a45146fd144659cae48ef5c6ce054d655b7cc/uv-0.2.26-py3-none-manylinux_2_28_aarch64.whl + sha256: c1ba6064f8bff59e3e6a7c59cf27ce4cffc6bf2eed1777134522b65c562f9206 requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.26 - url: https://files.pythonhosted.org/packages/0f/b6/cbb68a3b7faf7afa406d38b6d94065f759cac1b13a0a15dffa5bf7d7b60f/uv-0.2.26-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 65120080bbd2f2ce47e92f6065e223f2f416feb3a323ea9574d3e993b7ebde9f + url: https://files.pythonhosted.org/packages/ee/d1/d0311b79198f5f07809edcb6b71f38f8e8e0d848194ff0f5bfcd1cd941fe/uv-0.2.26-py3-none-win_amd64.whl + sha256: 05949e0135d5093d555f17ca6701e5939547d8a656bec003b7986e3540533348 requires_python: '>=3.8' - kind: pypi name: uv @@ -42424,8 +42424,8 @@ packages: - kind: pypi name: uv version: 0.2.27 - url: https://files.pythonhosted.org/packages/ed/1d/74d7009e57a85c6baedfb7bdf51481523b4a931eddb106c89f287dc278c8/uv-0.2.27-py3-none-win_amd64.whl - sha256: 7921c9eb9feb3b7a9cb6f4afab58718a5a07752d834c2de72b7d294bff963789 + url: https://files.pythonhosted.org/packages/be/53/b3e7e74acc2cf91861abfaabf11255df26d82871e1d3fcfec1c3c9b6dcd0/uv-0.2.27-py3-none-macosx_11_0_arm64.whl + sha256: 8a44fc58726f353645c64ccde00338e73fa97aa42bbeb3bd6a8269c0b9386954 requires_python: '>=3.8' - kind: pypi name: uv @@ -42442,20 +42442,20 @@ packages: - kind: pypi name: uv version: 0.2.27 - url: https://files.pythonhosted.org/packages/be/53/b3e7e74acc2cf91861abfaabf11255df26d82871e1d3fcfec1c3c9b6dcd0/uv-0.2.27-py3-none-macosx_11_0_arm64.whl - sha256: 8a44fc58726f353645c64ccde00338e73fa97aa42bbeb3bd6a8269c0b9386954 + url: https://files.pythonhosted.org/packages/ed/1d/74d7009e57a85c6baedfb7bdf51481523b4a931eddb106c89f287dc278c8/uv-0.2.27-py3-none-win_amd64.whl + sha256: 7921c9eb9feb3b7a9cb6f4afab58718a5a07752d834c2de72b7d294bff963789 requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.28 - url: https://files.pythonhosted.org/packages/80/d2/b8206aa8b4de05388cae473f87a06e6be80cfcc6ba6dd8313a4be9647252/uv-0.2.28-py3-none-manylinux_2_28_aarch64.whl - sha256: 894a9929f8deb9c15cf84c98fb89e8e2c3dcf6e9fd6da8c81e7b9a22c86d661e + url: https://files.pythonhosted.org/packages/69/68/34dc06721be38c4d90c717a34d8d0f7441d83d8f0efb2126a7026204e7dc/uv-0.2.28-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 8fc4185ee3bc644e38421a82a942fa5c7864d6eeaa04fd59e1ae577e2e5b76ea requires_python: '>=3.8' - kind: pypi name: uv version: 0.2.28 - url: https://files.pythonhosted.org/packages/69/68/34dc06721be38c4d90c717a34d8d0f7441d83d8f0efb2126a7026204e7dc/uv-0.2.28-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 8fc4185ee3bc644e38421a82a942fa5c7864d6eeaa04fd59e1ae577e2e5b76ea + url: https://files.pythonhosted.org/packages/80/d2/b8206aa8b4de05388cae473f87a06e6be80cfcc6ba6dd8313a4be9647252/uv-0.2.28-py3-none-manylinux_2_28_aarch64.whl + sha256: 894a9929f8deb9c15cf84c98fb89e8e2c3dcf6e9fd6da8c81e7b9a22c86d661e requires_python: '>=3.8' - kind: conda name: vc @@ -42671,32 +42671,32 @@ packages: - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d + url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 + url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/fd/03/c188ac517f402775b90d6f312955a5e53b866c964b32119f2ed76315697e/wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09 + url: https://files.pythonhosted.org/packages/0f/16/ea627d7817394db04518f62934a5de59874b587b792300991b3c347ff5e0/wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl - sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 + url: https://files.pythonhosted.org/packages/7f/a7/f1212ba098f3de0fd244e2de0f8791ad2539c03bef6c05a9fcb03e45b089/wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389 requires_python: '>=3.6' - kind: pypi name: wrapt version: 1.16.0 - url: https://files.pythonhosted.org/packages/6e/52/2da48b35193e39ac53cfb141467d9f259851522d0e8c87153f0ba4205fb1/wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: 72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1 + url: https://files.pythonhosted.org/packages/cf/c3/0084351951d9579ae83a3d9e38c140371e4c6b038136909235079f2e6e78/wrapt-1.16.0-cp311-cp311-win_amd64.whl + sha256: aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89 requires_python: '>=3.6' - kind: conda name: x264 @@ -43804,8 +43804,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/e8/46/66d5b55f4d737dd6ab75851b224abf0afe5774976fe511a54d2eb9063a41/zstandard-0.23.0-cp311-cp311-macosx_11_0_arm64.whl - sha256: 77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 + url: https://files.pythonhosted.org/packages/9e/40/f67e7d2c25a0e2dc1744dd781110b0b60306657f8696cafb7ad7579469bd/zstandard-0.23.0-cp311-cp311-macosx_10_9_x86_64.whl + sha256: 34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -43813,8 +43813,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/63/b6/677e65c095d8e12b66b8f862b069bcf1f1d781b9c9c6f12eb55000d57583/zstandard-0.23.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - sha256: 983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a + url: https://files.pythonhosted.org/packages/76/3f/dbafccf19cfeca25bbabf6f2dd81796b7218f768ec400f043edc767015a6/zstandard-0.23.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -43822,8 +43822,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/9e/40/f67e7d2c25a0e2dc1744dd781110b0b60306657f8696cafb7ad7579469bd/zstandard-0.23.0-cp311-cp311-macosx_10_9_x86_64.whl - sha256: 34895a41273ad33347b2fc70e1bff4240556de3c46c6ea430a7ed91f9042aa4e + url: https://files.pythonhosted.org/packages/e8/46/66d5b55f4d737dd6ab75851b224abf0afe5774976fe511a54d2eb9063a41/zstandard-0.23.0-cp311-cp311-macosx_11_0_arm64.whl + sha256: 77ea385f7dd5b5676d7fd943292ffa18fbf5c72ba98f7d09fc1fb9e819b34c23 requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -43831,8 +43831,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/be/a2/4272175d47c623ff78196f3c10e9dc7045c1b9caf3735bf041e65271eca4/zstandard-0.23.0-cp311-cp311-win_amd64.whl - sha256: 62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 + url: https://files.pythonhosted.org/packages/63/b6/677e65c095d8e12b66b8f862b069bcf1f1d781b9c9c6f12eb55000d57583/zstandard-0.23.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + sha256: 983b6efd649723474f29ed42e1467f90a35a74793437d0bc64a5bf482bedfa0a requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' @@ -43840,8 +43840,8 @@ packages: - kind: pypi name: zstandard version: 0.23.0 - url: https://files.pythonhosted.org/packages/76/3f/dbafccf19cfeca25bbabf6f2dd81796b7218f768ec400f043edc767015a6/zstandard-0.23.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - sha256: fd30d9c67d13d891f2360b2a120186729c111238ac63b43dbd37a5a40670b8ca + url: https://files.pythonhosted.org/packages/be/a2/4272175d47c623ff78196f3c10e9dc7045c1b9caf3735bf041e65271eca4/zstandard-0.23.0-cp311-cp311-win_amd64.whl + sha256: 62136da96a973bd2557f06ddd4e8e807f9e13cbb0bfb9cc06cfe6d98ea90dfe0 requires_dist: - cffi>=1.11 ; platform_python_implementation == 'PyPy' - cffi>=1.11 ; extra == 'cffi' diff --git a/rerun_cpp/src/rerun/c/sdk_info.h b/rerun_cpp/src/rerun/c/sdk_info.h index 923a45481ea1..241f946094c0 100644 --- a/rerun_cpp/src/rerun/c/sdk_info.h +++ b/rerun_cpp/src/rerun/c/sdk_info.h @@ -2,7 +2,7 @@ /// /// 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.19.0-alpha.2" +#define RERUN_SDK_HEADER_VERSION "0.19.0-alpha.3" /// Major version of the Rerun C SDK. #define RERUN_SDK_HEADER_VERSION_MAJOR 0 diff --git a/rerun_js/web-viewer-react/README.md b/rerun_js/web-viewer-react/README.md index ac9aa84c12c4..184f4ba231bd 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 c66c3e1eacf7..a08246177af6 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.19.0-alpha.2", + "version": "0.19.0-alpha.3", "description": "Embed the Rerun web viewer in your React app", "licenses": [ { @@ -39,7 +39,7 @@ "tsconfig.json" ], "dependencies": { - "@rerun-io/web-viewer": "0.19.0-alpha.2", + "@rerun-io/web-viewer": "0.19.0-alpha.3", "@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 257cfe64366c..3888ab3c15c3 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 f419af823d63..581b70d6dda6 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.19.0-alpha.2", + "version": "0.19.0-alpha.3", "description": "Embed the Rerun web viewer in your app", "licenses": [ { diff --git a/rerun_notebook/pyproject.toml b/rerun_notebook/pyproject.toml index fe98c78cbc3e..947650ee043c 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.19.0-alpha.2" +version = "0.19.0-alpha.3" dependencies = ["anywidget", "jupyter-ui-poll"] readme = "README.md" keywords = ["rerun", "notebook"] diff --git a/rerun_py/pyproject.toml b/rerun_py/pyproject.toml index 668706fd7470..312fbfb96eb7 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.19.0-alpha.2"] +notebook = ["rerun-notebook==0.19.0-alpha.3"] [project.urls] documentation = "https://www.rerun.io/docs" diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index b9b37451ff9f..295fc19b805e 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -7,8 +7,8 @@ import numpy as np -__version__ = "0.19.0-alpha.2" -__version_info__ = (0, 19, 0, "alpha.2") +__version__ = "0.19.0-alpha.3" +__version_info__ = (0, 19, 0, "alpha.3") # ===================================== # API RE-EXPORTS From ce653855daeed9c625e68ea2e06c99887ffbc73b Mon Sep 17 00:00:00 2001 From: Jeremy Leibs Date: Mon, 14 Oct 2024 09:30:07 +0200 Subject: [PATCH 22/33] Make explicit recordings work without calling rr.init() (#7698) ### What Our recording functions would always check the global recording state even though they could validly operate just on a manually-created recording. With this change, this becomes valid: ``` import rerun as rr rec = rr.new_recording("rerun_example_cube_flat") rec.log("points", rr.Points3D([1, 2, 3])) rec.save("output.rrd") ``` --- rerun_py/rerun_sdk/rerun/sinks.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/rerun_py/rerun_sdk/rerun/sinks.py b/rerun_py/rerun_sdk/rerun/sinks.py index d86f35f28fef..c38cf6a3eddd 100644 --- a/rerun_py/rerun_sdk/rerun/sinks.py +++ b/rerun_py/rerun_sdk/rerun/sinks.py @@ -13,6 +13,12 @@ # --- Sinks --- +def is_recording_enabled(recording: RecordingStream | None) -> bool: + if recording is not None: + return bindings.is_enabled(recording.inner) # type: ignore[no-any-return] + return bindings.is_enabled() # type: ignore[no-any-return] + + def connect( addr: str | None = None, *, @@ -47,7 +53,7 @@ def connect( """ - if not bindings.is_enabled(): + if not is_recording_enabled(recording): logging.warning("Rerun is disabled - connect() call ignored") return @@ -102,7 +108,7 @@ def save( """ - if not bindings.is_enabled(): + if not is_recording_enabled(recording): logging.warning("Rerun is disabled - save() call ignored. You must call rerun.init before saving a recording.") return @@ -149,7 +155,7 @@ def stdout(default_blueprint: BlueprintLike | None = None, recording: RecordingS """ - if not bindings.is_enabled(): + if not is_recording_enabled(recording): logging.warning("Rerun is disabled - save() call ignored. You must call rerun.init before saving a recording.") return @@ -234,7 +240,7 @@ def serve( """ - if not bindings.is_enabled(): + if not is_recording_enabled(recording): logging.warning("Rerun is disabled - serve() call ignored") return @@ -346,7 +352,7 @@ def spawn( """ - if not bindings.is_enabled(): + if not is_recording_enabled(recording): logging.warning("Rerun is disabled - spawn() call ignored.") return From ca6ad4050b430b9e8e61cd54a947b80ba4c3fcad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jochen=20G=C3=B6rtler?= Date: Mon, 14 Oct 2024 09:31:03 +0200 Subject: [PATCH 23/33] Implement `From` for `bool` (#7686) --- crates/store/re_types/src/components/show_labels_ext.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/store/re_types/src/components/show_labels_ext.rs b/crates/store/re_types/src/components/show_labels_ext.rs index ce3b5ff9cd84..8914bba71ea0 100644 --- a/crates/store/re_types/src/components/show_labels_ext.rs +++ b/crates/store/re_types/src/components/show_labels_ext.rs @@ -8,3 +8,10 @@ impl Default for ShowLabels { Self(true.into()) } } + +impl From for bool { + #[inline] + fn from(value: ShowLabels) -> Self { + value.0.into() + } +} From 7d07612f85db7c90aa95a36220e3131bc6b3be1f Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:16:51 +0200 Subject: [PATCH 24/33] Add definitions for remote store gRPC API as well as the logic for building rust types from the proto definition We introduce re_remote_store_types with proto definition files for V0 remote store gRPC API. We also introduce re_remote_store_tpyes_builder that heaveily relies on tonic_build to build the actual rust code from protobuf files. --- ARCHITECTURE.md | 30 +- Cargo.lock | 533 ++++++++++-- Cargo.toml | 11 +- crates/build/README.md | 13 +- .../re_remote_store_types_builder/Cargo.toml | 26 + .../re_remote_store_types_builder/README.md | 12 + .../src/bin/build_re_remote_store_types.rs | 38 + .../re_remote_store_types_builder/src/lib.rs | 26 + crates/store/re_remote_store_types/Cargo.toml | 23 + crates/store/re_remote_store_types/README.md | 14 + .../proto/rerun/v0/common.proto | 117 +++ .../proto/rerun/v0/remote_store.proto | 91 +++ crates/store/re_remote_store_types/src/lib.rs | 217 +++++ .../src/v0/rerun.remote_store.v0.rs | 760 ++++++++++++++++++ crates/store/re_ws_comms/src/client.rs | 3 +- deny.toml | 2 +- pixi.toml | 3 + scripts/lint.py | 1 + 18 files changed, 1846 insertions(+), 74 deletions(-) create mode 100644 crates/build/re_remote_store_types_builder/Cargo.toml create mode 100644 crates/build/re_remote_store_types_builder/README.md create mode 100644 crates/build/re_remote_store_types_builder/src/bin/build_re_remote_store_types.rs create mode 100644 crates/build/re_remote_store_types_builder/src/lib.rs create mode 100644 crates/store/re_remote_store_types/Cargo.toml create mode 100644 crates/store/re_remote_store_types/README.md create mode 100644 crates/store/re_remote_store_types/proto/rerun/v0/common.proto create mode 100644 crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto create mode 100644 crates/store/re_remote_store_types/src/lib.rs create mode 100644 crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 376d4fb5167b..cdd9347e7980 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -159,14 +159,15 @@ Update instructions: ### Application-level store -| Crate | Description | -|----------------------|--------------------------------------------------------------------------| -| re_entity_db | In-memory storage of Rerun entities | -| re_query | Querying data in the re_chunk_store | -| re_dataframe | The Rerun public data APIs. | -| re_types | The built-in Rerun data types, component types, and archetypes. | -| re_types_blueprint | The core traits and types that power Rerun's Blueprint sub-system. | -| re_log_encoding | Helpers for encoding and transporting Rerun log messages | +| Crate | Description | +|-----------------------|--------------------------------------------------------------------------| +| re_entity_db | In-memory storage of Rerun entities | +| re_query | Querying data in the re_chunk_store | +| re_dataframe | The Rerun public data APIs. | +| re_remote_store_types | Rerun remote store gRPC API types | +| re_types | The built-in Rerun data types, component types, and archetypes. | +| re_types_blueprint | The core traits and types that power Rerun's Blueprint sub-system. | +| re_log_encoding | Helpers for encoding and transporting Rerun log messages | ### Low-level store @@ -193,12 +194,13 @@ Update instructions: ### Build support -| Crate | Description | -|----------------------------|------------------------------------------------------------------| -| re_build_info | Information about the build. Use together with re_build_tools | -| re_build_tools | build.rs helpers for generating build info | -| re_types_builder | Generates code for Rerun's SDKs from flatbuffers definitions. | -| re_dev_tools | Various tools for Rerun development. Each tool has a subcommand. | +| Crate | Description | +|-------------------------------|------------------------------------------------------------------| +| re_build_info | Information about the build. Use together with re_build_tools | +| re_build_tools | build.rs helpers for generating build info | +| re_remote_store_types_builder | Generates code for Rerun remote store gRPC API | +| re_types_builder | Generates code for Rerun's SDKs from flatbuffers definitions. | +| re_dev_tools | Various tools for Rerun development. Each tool has a subcommand. | ### Utilities diff --git a/Cargo.lock b/Cargo.lock index 3d4b1a2a5097..1cd9c25fdcee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -630,7 +630,7 @@ dependencies = [ "polling 2.8.0", "rustix 0.37.27", "slab", - "socket2", + "socket2 0.4.9", "waker-fn", ] @@ -731,6 +731,28 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "async-task" version = "4.4.0" @@ -851,6 +873,53 @@ dependencies = [ "thiserror", ] +[[package]] +name = "axum" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 1.0.1", + "tower 0.5.1", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", +] + [[package]] name = "az" version = "1.2.1" @@ -878,12 +947,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -1025,9 +1088,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "calloop" @@ -2275,8 +2338,7 @@ dependencies = [ [[package]] name = "ewebsock" version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bbed098b2bf9abcfe50eeaa01ae77a2a1da931bdcd83d23fcd7b8f941cd52c9" +source = "git+https://github.com/rerun-io/ewebsock?rev=1a9e78aa18390511476f9e2c0453502f11a7aa78#1a9e78aa18390511476f9e2c0453502f11a7aa78" dependencies = [ "document-features", "js-sys", @@ -2725,6 +2787,25 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.1.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.8.2" @@ -2844,15 +2925,38 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", "itoa", ] +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.8.0" @@ -2871,6 +2975,59 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2 0.5.7", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -3392,6 +3549,12 @@ dependencies = [ "libc", ] +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "matrixmultiply" version = "0.3.7" @@ -4122,8 +4285,8 @@ dependencies = [ "anyhow", "clap", "glam", - "prost", - "prost-build", + "prost 0.12.6", + "prost-build 0.12.6", "protoc-prebuilt", "re_build_tools", "rerun", @@ -4526,7 +4689,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.12.6", +] + +[[package]] +name = "prost" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +dependencies = [ + "bytes", + "prost-derive 0.13.3", ] [[package]] @@ -4543,8 +4716,29 @@ dependencies = [ "once_cell", "petgraph", "prettyplease", - "prost", - "prost-types", + "prost 0.12.6", + "prost-types 0.12.6", + "regex", + "syn 2.0.48", + "tempfile", +] + +[[package]] +name = "prost-build" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" +dependencies = [ + "bytes", + "heck 0.4.1", + "itertools 0.13.0", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost 0.13.3", + "prost-types 0.13.3", "regex", "syn 2.0.48", "tempfile", @@ -4563,13 +4757,35 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "prost-derive" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +dependencies = [ + "anyhow", + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "prost-types" version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ - "prost", + "prost 0.12.6", +] + +[[package]] +name = "prost-types" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +dependencies = [ + "prost 0.13.3", ] [[package]] @@ -5398,6 +5614,31 @@ dependencies = [ "thiserror", ] +[[package]] +name = "re_remote_store_types" +version = "0.19.0-alpha.1+dev" +dependencies = [ + "prost 0.13.3", + "re_dataframe", + "re_log_types", + "thiserror", + "tonic", + "tonic-build", +] + +[[package]] +name = "re_remote_store_types_builder" +version = "0.19.0-alpha.1+dev" +dependencies = [ + "camino", + "re_dataframe", + "re_log", + "re_log_types", + "re_tracing", + "tonic", + "tonic-build", +] + [[package]] name = "re_renderer" version = "0.19.0-alpha.3" @@ -6710,23 +6951,33 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.11" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ "log", + "once_cell", "ring", + "rustls-pki-types", "rustls-webpki", - "sct", + "subtle", + "zeroize", ] +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + [[package]] name = "rustls-webpki" -version = "0.101.7" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", + "rustls-pki-types", "untrusted", ] @@ -6763,16 +7014,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "semver" version = "1.0.17" @@ -6987,9 +7228,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ "serde", ] @@ -7062,6 +7303,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "spawn_viewer" version = "0.19.0-alpha.3" @@ -7137,6 +7388,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7986063f7c0ab374407e586d7048a3d5aac94f103f751088bf398e07cd5400" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -7159,6 +7416,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "sysinfo" version = "0.30.2" @@ -7417,6 +7686,57 @@ dependencies = [ "ahash", ] +[[package]] +name = "tokio" +version = "1.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2 0.5.7", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.8.19" @@ -7463,6 +7783,96 @@ dependencies = [ "winnow 0.6.18", ] +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost 0.13.3", + "socket2 0.5.7", + "tokio", + "tokio-stream", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build 0.13.3", + "prost-types 0.13.3", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.40" @@ -7495,6 +7905,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "ttf-parser" version = "0.19.0" @@ -7503,9 +7919,9 @@ checksum = "44dcf002ae3b32cd25400d6df128c5babec3927cd1eb7ce813cfff20eb6c3746" [[package]] name = "tungstenite" -version = "0.20.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" dependencies = [ "byteorder", "bytes", @@ -7515,11 +7931,11 @@ dependencies = [ "log", "rand", "rustls", + "rustls-pki-types", "sha1", "thiserror", - "url", "utf-8", - "webpki-roots 0.24.0", + "webpki-roots", ] [[package]] @@ -7625,20 +8041,20 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.1" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "flate2", "log", "once_cell", "rustls", - "rustls-webpki", + "rustls-pki-types", "serde", "serde_json", "url", - "webpki-roots 0.25.4", + "webpki-roots", ] [[package]] @@ -7741,6 +8157,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -8079,19 +8504,13 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.24.0" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ - "rustls-webpki", + "rustls-pki-types", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "weezl" version = "0.1.7" @@ -8759,6 +9178,12 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + [[package]] name = "zip" version = "0.6.6" diff --git a/Cargo.toml b/Cargo.toml index 95963b894fa7..a3bd3b3a8851 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ version = "0.19.0-alpha.3" re_build_info = { path = "crates/build/re_build_info", version = "=0.19.0-alpha.3", default-features = false } re_build_tools = { path = "crates/build/re_build_tools", version = "=0.19.0-alpha.3", default-features = false } re_dev_tools = { path = "crates/build/re_dev_tools", version = "=0.19.0-alpha.3", default-features = false } +re_remote_store_types_builder = { path = "crates/build/re_remote_store_types_builder", version = "=0.19.0-alpha.3", default-features = false } re_types_builder = { path = "crates/build/re_types_builder", version = "=0.19.0-alpha.3", default-features = false } # crates/store: @@ -50,6 +51,7 @@ re_format_arrow = { path = "crates/store/re_format_arrow", version = "=0.19.0-al re_log_encoding = { path = "crates/store/re_log_encoding", version = "=0.19.0-alpha.3", default-features = false } re_log_types = { path = "crates/store/re_log_types", version = "=0.19.0-alpha.3", default-features = false } re_query = { path = "crates/store/re_query", version = "=0.19.0-alpha.3", default-features = false } +re_remote_store_types = { path = "crates/store/re_remote_store_types", version = "=0.19.0-alpha.3", default-features = false } re_sdk_comms = { path = "crates/store/re_sdk_comms", version = "=0.19.0-alpha.3", default-features = false } re_types = { path = "crates/store/re_types", version = "=0.19.0-alpha.3", default-features = false } re_types_blueprint = { path = "crates/store/re_types_blueprint", version = "=0.19.0-alpha.3", default-features = false } @@ -103,7 +105,7 @@ re_viewport_blueprint = { path = "crates/viewer/re_viewport_blueprint", version re_web_viewer_server = { path = "crates/viewer/re_web_viewer_server", version = "=0.19.0-alpha.3", default-features = false } # Rerun crates in other repos: -ewebsock = "0.6.0" +ewebsock = { git = "https://github.com/rerun-io/ewebsock", rev = "1a9e78aa18390511476f9e2c0453502f11a7aa78" } re_math = "0.20.0" # egui-crates: @@ -222,6 +224,7 @@ pollster = "0.3" prettyplease = "0.2" proc-macro2 = { version = "1.0", default-features = false } profiling = { version = "1.0.12", default-features = false } +prost = "0.13.3" puffin = "0.19.1" puffin_http = "0.16" pyo3 = "0.21.2" @@ -261,12 +264,14 @@ tinystl = { version = "0.0.3", default-features = false } tinyvec = { version = "1.6", features = ["alloc", "rustc_1_55"] } tobj = "4.0" toml = { version = "0.8.10", default-features = false } +tonic = "0.12.3" +tonic-build = "0.12.3" tracing = { version = "0.1", default-features = false } -tungstenite = { version = "0.20", default-features = false } +tungstenite = { version = "0.23", default-features = false } type-map = "0.5" typenum = "1.15" unindent = "0.2" -ureq = "2.6" +ureq = "2.9.2" url = "2.3" uuid = "1.1" vec1 = "1.8" diff --git a/crates/build/README.md b/crates/build/README.md index 8e09a075d66f..615f8490ad09 100644 --- a/crates/build/README.md +++ b/crates/build/README.md @@ -1 +1,12 @@ -Crates run at build-time +# re_remote_store_types_builder + +Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. + +[![Latest version](https://img.shields.io/crates/v/re_remote_store_types_builder.svg)](https://crates.io/crates/re_remote_store_types_builder) +[![Documentation](https://docs.rs/re_remote_store_types_builder/badge.svg)](https://docs.rs/re_remote_store_types_builder) +![MIT](https://img.shields.io/badge/license-MIT-blue.svg) +![Apache](https://img.shields.io/badge/license-Apache-blue.svg) + +This crate implements Rerun's code generation for the remote store node gRPC API definition. + +You can generate the code with `pixi run codegen-rstore`. diff --git a/crates/build/re_remote_store_types_builder/Cargo.toml b/crates/build/re_remote_store_types_builder/Cargo.toml new file mode 100644 index 000000000000..348173742ed2 --- /dev/null +++ b/crates/build/re_remote_store_types_builder/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "re_remote_store_types_builder" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +re_dataframe.workspace = true +re_log = { workspace = true, features = ["setup"] } +re_log_types.workspace = true +re_tracing = { workspace = true, features = ["server"] } + +# External +camino.workspace = true +tonic.workspace = true +tonic-build.workspace = true + +[lints] +workspace = true diff --git a/crates/build/re_remote_store_types_builder/README.md b/crates/build/re_remote_store_types_builder/README.md new file mode 100644 index 000000000000..615f8490ad09 --- /dev/null +++ b/crates/build/re_remote_store_types_builder/README.md @@ -0,0 +1,12 @@ +# re_remote_store_types_builder + +Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. + +[![Latest version](https://img.shields.io/crates/v/re_remote_store_types_builder.svg)](https://crates.io/crates/re_remote_store_types_builder) +[![Documentation](https://docs.rs/re_remote_store_types_builder/badge.svg)](https://docs.rs/re_remote_store_types_builder) +![MIT](https://img.shields.io/badge/license-MIT-blue.svg) +![Apache](https://img.shields.io/badge/license-Apache-blue.svg) + +This crate implements Rerun's code generation for the remote store node gRPC API definition. + +You can generate the code with `pixi run codegen-rstore`. diff --git a/crates/build/re_remote_store_types_builder/src/bin/build_re_remote_store_types.rs b/crates/build/re_remote_store_types_builder/src/bin/build_re_remote_store_types.rs new file mode 100644 index 000000000000..f70dc0cca261 --- /dev/null +++ b/crates/build/re_remote_store_types_builder/src/bin/build_re_remote_store_types.rs @@ -0,0 +1,38 @@ +//! This binary runs the remote store gRPC service codegen manually. +//! +//! It is easiest to call this using `pixi run codegen-rstore`, +//! which will set up the necessary tools. + +#![allow(clippy::unwrap_used)] + +use camino::Utf8Path; + +const PROTOBUF_DEFINITIONS_DIR_PATH: &str = "crates/store/re_remote_store_types/proto"; +const PROTOBUF_REMOTE_STORE_V0_RELATIVE_PATH: &str = "rerun/v0/remote_store.proto"; +const RUST_V0_OUTPUT_DIR_PATH: &str = "crates/store/re_remote_store_types/src/v0"; + +fn main() { + re_log::setup_logging(); + + let workspace_dir = Utf8Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .and_then(|p| p.parent()) + .and_then(|p| p.parent()) + .unwrap(); + + assert!( + workspace_dir.join("CODE_OF_CONDUCT.md").exists(), + "failed to find workspace root" + ); + + let definitions_dir_path = workspace_dir.join(PROTOBUF_DEFINITIONS_DIR_PATH); + let rust_generated_output_dir_path = workspace_dir.join(RUST_V0_OUTPUT_DIR_PATH); + + re_log::info!("Running codegen for storage node types"); + + re_remote_store_types_builder::generate_rust_code( + definitions_dir_path, + &[PROTOBUF_REMOTE_STORE_V0_RELATIVE_PATH], + rust_generated_output_dir_path, + ); +} diff --git a/crates/build/re_remote_store_types_builder/src/lib.rs b/crates/build/re_remote_store_types_builder/src/lib.rs new file mode 100644 index 000000000000..f9ca751381a2 --- /dev/null +++ b/crates/build/re_remote_store_types_builder/src/lib.rs @@ -0,0 +1,26 @@ +//! This crate contains logic for generating remote store gRPC API types as defined in +//! `re_remote_store_types` proto files. We are currently generating both client and server +//! definitions in the same file. +//! + +#![allow(clippy::unwrap_used)] + +use std::path::Path; + +/// Generate rust from from protobuf definitions. We rely on `tonic_build` to do the heavy lifting. +/// `tonic_build` relies on `prost` which itself relies on `protoc`. +/// +/// Note: make sure to invoke this via `pixi run codegen-rstore` in order to use the right `protoc` version. +pub fn generate_rust_code( + definitions_dir: impl AsRef, + proto_paths: &[impl AsRef], + output_dir: impl AsRef, +) { + tonic_build::configure() + .out_dir(output_dir.as_ref()) + .build_client(true) + .build_server(true) + .build_transport(true) + .compile_protos(proto_paths, &[definitions_dir]) + .unwrap(); +} diff --git a/crates/store/re_remote_store_types/Cargo.toml b/crates/store/re_remote_store_types/Cargo.toml new file mode 100644 index 000000000000..5db04a5a089a --- /dev/null +++ b/crates/store/re_remote_store_types/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "re_remote_store_types" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +include.workspace = true +license.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + +[dependencies] +re_log_types.workspace = true +re_dataframe.workspace = true + +# External +prost.workspace = true +thiserror.workspace = true +tonic.workspace = true +tonic-build.workspace = true + +[lints] +workspace = true diff --git a/crates/store/re_remote_store_types/README.md b/crates/store/re_remote_store_types/README.md new file mode 100644 index 000000000000..418df5c16895 --- /dev/null +++ b/crates/store/re_remote_store_types/README.md @@ -0,0 +1,14 @@ +# re_remote_store_types + +Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. + +[![Latest version](https://img.shields.io/crates/v/re_remote_store_types.svg)](https://crates.io/crates/re_remote_store_types) +[![Documentation](https://docs.rs/re_remote_store_types/badge.svg)](https://docs.rs/re_remote_store_types) +![MIT](https://img.shields.io/badge/license-MIT-blue.svg) +![Apache](https://img.shields.io/badge/license-Apache-blue.svg) + +Rerun remote store node gRPC API service types (client and server). + +This crate includes both the language-agnostic definitions (protobuf) as well as the generated code. + +The code is generated with `pixi run codegen-rstore`. diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto new file mode 100644 index 000000000000..072cff95f2a5 --- /dev/null +++ b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto @@ -0,0 +1,117 @@ +syntax = "proto3"; + +package rerun.remote_store.v0; + +// unique recording identifier. At this point in time it is the same id as the ChunkStore's StoreId +message RecordingId { + string id = 1; +} + +// A recording can have multiple timelines, each is identified by a name, for example `log_tick`, `log_time`, etc. +message Timeline { + string name = 1; +} + +// A time range between start and end time points. Each 64 bit number can represent different time point data +// depending on the timeline it is associated with. +message TimeRange { + int64 start = 1; + int64 end = 2; +} + +// arrow IPC serialized schema +message Schema { + bytes arrow_schema = 1; +} + +message Query { + // database view defined by entity paths and components + ViewContents view_contents = 1; + // filtering index (just a string i.e. a name of the timeline for starters) + IndexColumnSelector filtered_index = 2; + // Optional specific range for the index selector + IndexRange filtered_index_range = 3; + // Optional specific values for the index selector + IndexValues filtered_index_values = 4; + // Optional index selector sampling + IndexValues using_index_values = 5; + // PoV (filtering) component + ComponentColumnSelector filtered_pov = 6; + // which columns to include in the response + // Note - we have one more layer of indiraction to ensure the field is optional, + // same as in the query expression. We can't have both 'repeated' and 'optional' field labels. + ColumnSelection column_selection = 7; + // how are null values filled in the response + SparseFillStrategy sparse_fill_strategy = 8; +} + +message ColumnSelection { + repeated ColumnSelector columns = 1; +} + +message ColumnSelector { + oneof selector_type { + ComponentColumnSelector component_column = 2; + TimeColumnSelector time_column = 3; + } +} + +message IndexColumnSelector { + // TODO (zehiko) we need to add support for other types of index selectors + Timeline timeline = 1; +} + +message IndexRange { + // TODO (zehiko) support for other ranges for other index selectors + TimeRange time_range = 1; +} + +message IndexValues { + // TODO (zehiko) we need to add support for other types of index selectors + repeated TimeInt time_points = 1; +} + +message SampledIndexValues { + repeated TimeInt sample_points = 1; +} + +message TimeInt { + int64 time = 1; +} + +message ViewContents { + repeated ViewContentsPart contents = 1; +} + +message ViewContentsPart { + EntityPath path = 1; + ComponentsSet components = 2; +} + +message ComponentsSet { + repeated Component components = 1; +} + +message EntityPath { + string path = 1; +} + +message Component { + // component name needs to be a string as user can define their own component + string name = 1; +} + +message TimeColumnSelector { + Timeline timeline = 1; +} + +message ComponentColumnSelector { + EntityPath entity_path = 1; + Component component = 2; + // TODO do we need join encoding? +} + +enum SparseFillStrategy { + NONE = 0; + LATEST_AL_GLOBAL = 1; +} diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto new file mode 100644 index 000000000000..8be53c1a0ffe --- /dev/null +++ b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto @@ -0,0 +1,91 @@ +syntax = "proto3"; + +package rerun.remote_store.v0; + +import "rerun/v0/common.proto"; + +service StorageNode { + rpc ListRecordings(ListRecordingsRequest) returns (ListRecordingsResponse) {} + rpc Query(QueryRequest) returns (stream QueryResponse) {} + rpc GetRecordingMetadata(GetRecordingMetadataRequest) returns (GetRecordingMetadataResponse) {} + // TODO (zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings + rpc RegisterRecordings(RegisterRecordingsRequest) returns (RegisterRecordingsResponse) {} +} + +// ---------------- RegisterRecording ------------------ + +message RegisterRecordingsRequest { + string description = 1; + ObjectStorage obj_storage = 2; + // TODO (zehiko) should this be auto-discoverable? + RecordingType typ = 3; +} + +message ObjectStorage { + string bucket_name = 1; + string url = 2; +} + +message RegisterRecordingsResponse { + // Note / TODO (zehiko): this implies we read the record (for example go through entire .rrd file + // chunk by chunk) and extract the metadata. So we might want to 1/ not do this i.e. + // only do it as part of explicit GetMetadata request or 2/ do it if Request has "include_metadata=true" + // or 3/ do it always + repeated RecordingMetadata metadata = 2; +} + +// ---------------- GetRecordingMetadata ----------------- + +message GetRecordingMetadataRequest { + RecordingId recording_id = 1; +} + +message GetRecordingMetadataResponse { + RecordingMetadata metadata = 1; +} + +message RecordingMetadata { + RecordingId id = 1; + Schema schema = 2; + repeated TimeMetadata time_metadata = 3; +} + +message TimeMetadata { + Timeline timeline = 1; + TimeRange time_range = 2; +} + +// ---------------- Query ----------------- + +message QueryRequest { + // unique identifier of the recording + RecordingId recording_id = 1; + // query to execute + Query query = 2; +} + +message QueryResponse { + // single record batch (encoding TBD - TODO). + bytes record_batch = 1; +} + + +// ----------------- ListRecordings ----------------- + +message ListRecordingsRequest {} + +message ListRecordingsResponse { + repeated RecordingInfo recordings = 1; +} + +message RecordingInfo { + RecordingId id = 1; + string description = 2; + string storage_url = 3; + uint64 size_bytes = 4; + RecordingType typ = 5; +} + +enum RecordingType { + RRD = 0; +} diff --git a/crates/store/re_remote_store_types/src/lib.rs b/crates/store/re_remote_store_types/src/lib.rs new file mode 100644 index 000000000000..f1a327ae94fd --- /dev/null +++ b/crates/store/re_remote_store_types/src/lib.rs @@ -0,0 +1,217 @@ +//! This crate contains generated types for the remote store gRPC service API. +//! Generation is done using the `re_remote_store_types_builder` crate. +//! +//! We want clear separation between 'internal' types and gRPC types and don't want +//! to use gRPC types in the rerun viewer codebase. That's why we implement all the +//! necessary conversion code (in the form of `From` and `TryFrom` traits) in this crate. +//! + +// Ignoring all warnings for the auto-generated code. +#![allow(clippy::doc_markdown)] +#![allow(clippy::derive_partial_eq_without_eq)] +#![allow(clippy::enum_variant_names)] +#![allow(clippy::unwrap_used)] +#![allow(clippy::wildcard_imports)] +#![allow(clippy::manual_is_variant_and)] +/// Generated types for the remote store gRPC service API v0. +pub mod v0 { + #[path = "../v0/rerun.remote_store.v0.rs"] + mod _v0; + + pub use self::_v0::*; + + // ==== below are all necessary transforms from internal rerun types to protobuf types ===== + + use std::collections::BTreeSet; + + #[derive(Debug, thiserror::Error)] + pub enum TypeConversionError { + #[error("missing required field: {0}")] + MissingField(&'static str), + } + + impl From for TimeRange { + fn from(time_range: re_log_types::ResolvedTimeRange) -> Self { + Self { + start: time_range.min().as_i64(), + end: time_range.max().as_i64(), + } + } + } + + impl TryFrom for re_dataframe::external::re_chunk_store::QueryExpression { + type Error = TypeConversionError; + + fn try_from(value: Query) -> Result { + let filtered_index = value + .filtered_index + .ok_or(TypeConversionError::MissingField("filtered_index"))? + .try_into()?; + + let selection = value + .column_selection + .map(|cs| { + cs.columns + .into_iter() + .map(|c| { + re_dataframe::external::re_chunk_store::ColumnSelector::try_from(c) + }) + .collect::, _>>() + }) + .transpose()?; + + let filtered_point_of_view = value + .filtered_pov + .map(|fp| { + re_dataframe::external::re_chunk_store::ComponentColumnSelector::try_from(fp) + }) + .transpose()?; + + Ok(Self { + view_contents: value.view_contents.map(|vc| vc.into()), + filtered_index, + filtered_index_range: value + .filtered_index_range + .map(|ir| ir.try_into()) + .transpose()?, + filtered_index_values: value + .filtered_index_values + .map(|iv| iv.time_points.into_iter().map(|v| v.into()).collect()), + using_index_values: value + .using_index_values + .map(|uiv| uiv.time_points.into_iter().map(|v| v.into()).collect()), + filtered_point_of_view, + sparse_fill_strategy: + re_dataframe::external::re_chunk_store::SparseFillStrategy::default(), // TODO(zehiko) implement support for sparse fill strategy + selection, + }) + } + } + + impl From for re_dataframe::external::re_chunk_store::ViewContentsSelector { + fn from(value: ViewContents) -> Self { + value + .contents + .into_iter() + .map(|part| { + // TODO(zehiko) option unwrap + let entity_path = Into::::into(part.path.unwrap()); + let column_selector = part.components.map(|cs| { + cs.components + .into_iter() + .map(|c| re_dataframe::external::re_chunk::ComponentName::new(&c.name)) + .collect::>() + }); + (entity_path, column_selector) + }) + .collect::() + } + } + + impl From for re_log_types::EntityPath { + fn from(value: EntityPath) -> Self { + Self::from(value.path) + } + } + + impl TryFrom for re_log_types::Timeline { + type Error = TypeConversionError; + + fn try_from(value: IndexColumnSelector) -> Result { + let timeline_name = value + .timeline + .ok_or(TypeConversionError::MissingField("timeline"))? + .name; + + #[allow(clippy::match_same_arms)] + let timeline = match timeline_name.as_str() { + "log_time" => Self::new_temporal(timeline_name), + "log_tick" => Self::new_sequence(timeline_name), + "frame" => Self::new_sequence(timeline_name), + "frame_nr" => Self::new_sequence(timeline_name), + _ => Self::new_temporal(timeline_name), + }; + + Ok(timeline) + } + } + + impl TryFrom for re_dataframe::external::re_chunk_store::IndexRange { + type Error = TypeConversionError; + + fn try_from(value: IndexRange) -> Result { + let time_range = value + .time_range + .ok_or(TypeConversionError::MissingField("time_range"))?; + + Ok(Self::new(time_range.start, time_range.end)) + } + } + + impl From for re_log_types::TimeInt { + fn from(value: TimeInt) -> Self { + Self::new_temporal(value.time) + } + } + + impl TryFrom + for re_dataframe::external::re_chunk_store::ComponentColumnSelector + { + type Error = TypeConversionError; + + fn try_from(value: ComponentColumnSelector) -> Result { + let entity_path = value + .entity_path + .ok_or(TypeConversionError::MissingField("entity_path"))? + .into(); + + let component = value + .component + .ok_or(TypeConversionError::MissingField("component"))? + .name; + + Ok(Self { + entity_path, + component: re_dataframe::external::re_chunk::ComponentName::new(&component), + join_encoding: re_dataframe::external::re_chunk_store::JoinEncoding::default(), // TODO(zehiko) implement + }) + } + } + + impl TryFrom for re_dataframe::external::re_chunk_store::TimeColumnSelector { + type Error = TypeConversionError; + + fn try_from(value: TimeColumnSelector) -> Result { + let timeline = value + .timeline + .ok_or(TypeConversionError::MissingField("timeline"))?; + + Ok(Self { + timeline: timeline.name.into(), + }) + } + } + + impl TryFrom for re_dataframe::external::re_chunk_store::ColumnSelector { + type Error = TypeConversionError; + + fn try_from(value: ColumnSelector) -> Result { + match value + .selector_type + .ok_or(TypeConversionError::MissingField("selector_type"))? + { + column_selector::SelectorType::ComponentColumn(component_column_selector) => { + let selector: re_dataframe::external::re_chunk_store::ComponentColumnSelector = + component_column_selector.try_into()?; + Ok(selector.into()) + } + column_selector::SelectorType::TimeColumn(time_column_selector) => { + let selector: re_dataframe::external::re_chunk_store::TimeColumnSelector = + time_column_selector.try_into()?; + + Ok(selector.into()) + } + } + } + } +} diff --git a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs new file mode 100644 index 000000000000..8ba9fadd7e2a --- /dev/null +++ b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs @@ -0,0 +1,760 @@ +// This file is @generated by prost-build. +/// unique recording identifier. At this point in time it is the same id as the ChunkStore's StoreId +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RecordingId { + #[prost(string, tag = "1")] + pub id: ::prost::alloc::string::String, +} +/// A recording can have multiple timelines, each is identified by a name, for example `log_tick`, `log_time`, etc. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Timeline { + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, +} +/// A time range between start and end time points. Each 64 bit number can represent different time point data +/// depending on the timeline it is associated with. +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct TimeRange { + #[prost(int64, tag = "1")] + pub start: i64, + #[prost(int64, tag = "2")] + pub end: i64, +} +/// arrow IPC serialized schema +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Schema { + #[prost(bytes = "vec", tag = "1")] + pub arrow_schema: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Query { + /// database view defined by entity paths and components + #[prost(message, optional, tag = "1")] + pub view_contents: ::core::option::Option, + /// filtering index (just a string i.e. a name of the timeline for starters) + #[prost(message, optional, tag = "2")] + pub filtered_index: ::core::option::Option, + /// Optional specific range for the index selector + #[prost(message, optional, tag = "3")] + pub filtered_index_range: ::core::option::Option, + /// Optional specific values for the index selector + #[prost(message, optional, tag = "4")] + pub filtered_index_values: ::core::option::Option, + /// Optional index selector sampling + #[prost(message, optional, tag = "5")] + pub using_index_values: ::core::option::Option, + /// PoV (filtering) component + #[prost(message, optional, tag = "6")] + pub filtered_pov: ::core::option::Option, + /// which columns to include in the response + /// Note - we have one more layer of indiraction to ensure the field is optional, + /// same as in the query expression. We can't have both 'repeated' and 'optional' field labels. + #[prost(message, optional, tag = "7")] + pub column_selection: ::core::option::Option, + /// how are null values filled in the response + #[prost(enumeration = "SparseFillStrategy", tag = "8")] + pub sparse_fill_strategy: i32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ColumnSelection { + #[prost(message, repeated, tag = "1")] + pub columns: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ColumnSelector { + #[prost(oneof = "column_selector::SelectorType", tags = "2, 3")] + pub selector_type: ::core::option::Option, +} +/// Nested message and enum types in `ColumnSelector`. +pub mod column_selector { + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum SelectorType { + #[prost(message, tag = "2")] + ComponentColumn(super::ComponentColumnSelector), + #[prost(message, tag = "3")] + TimeColumn(super::TimeColumnSelector), + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IndexColumnSelector { + /// TODO (zehiko) we need to add support for other types of index selectors + #[prost(message, optional, tag = "1")] + pub timeline: ::core::option::Option, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct IndexRange { + /// TODO (zehiko) support for other ranges for other index selectors + #[prost(message, optional, tag = "1")] + pub time_range: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IndexValues { + /// TODO (zehiko) we need to add support for other types of index selectors + #[prost(message, repeated, tag = "1")] + pub time_points: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SampledIndexValues { + #[prost(message, repeated, tag = "1")] + pub sample_points: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct TimeInt { + #[prost(int64, tag = "1")] + pub time: i64, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ViewContents { + #[prost(message, repeated, tag = "1")] + pub contents: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ViewContentsPart { + #[prost(message, optional, tag = "1")] + pub path: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub components: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ComponentsSet { + #[prost(message, repeated, tag = "1")] + pub components: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct EntityPath { + #[prost(string, tag = "1")] + pub path: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct Component { + /// component name needs to be a string as user can define their own component + #[prost(string, tag = "1")] + pub name: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TimeColumnSelector { + #[prost(message, optional, tag = "1")] + pub timeline: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ComponentColumnSelector { + #[prost(message, optional, tag = "1")] + pub entity_path: ::core::option::Option, + /// TODO do we need join encoding? + #[prost(message, optional, tag = "2")] + pub component: ::core::option::Option, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum SparseFillStrategy { + None = 0, + LatestAlGlobal = 1, +} +impl SparseFillStrategy { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::None => "NONE", + Self::LatestAlGlobal => "LATEST_AL_GLOBAL", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "NONE" => Some(Self::None), + "LATEST_AL_GLOBAL" => Some(Self::LatestAlGlobal), + _ => None, + } + } +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RegisterRecordingsRequest { + #[prost(string, tag = "1")] + pub description: ::prost::alloc::string::String, + #[prost(message, optional, tag = "2")] + pub obj_storage: ::core::option::Option, + /// TODO (zehiko) should this be auto-discoverable? + #[prost(enumeration = "RecordingType", tag = "3")] + pub typ: i32, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ObjectStorage { + #[prost(string, tag = "1")] + pub bucket_name: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub url: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RegisterRecordingsResponse { + /// Note / TODO (zehiko): this implies we read the record (for example go through entire .rrd file + /// chunk by chunk) and extract the metadata. So we might want to 1/ not do this i.e. + /// only do it as part of explicit GetMetadata request or 2/ do it if Request has "include_metadata=true" + /// or 3/ do it always + #[prost(message, repeated, tag = "2")] + pub metadata: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetRecordingMetadataRequest { + #[prost(message, optional, tag = "1")] + pub recording_id: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct GetRecordingMetadataResponse { + #[prost(message, optional, tag = "1")] + pub metadata: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RecordingMetadata { + #[prost(message, optional, tag = "1")] + pub id: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub schema: ::core::option::Option, + #[prost(message, repeated, tag = "3")] + pub time_metadata: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TimeMetadata { + #[prost(message, optional, tag = "1")] + pub timeline: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub time_range: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryRequest { + /// unique identifier of the recording + #[prost(message, optional, tag = "1")] + pub recording_id: ::core::option::Option, + /// query to execute + #[prost(message, optional, tag = "2")] + pub query: ::core::option::Option, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct QueryResponse { + /// single record batch (encoding TBD - TODO). + #[prost(bytes = "vec", tag = "1")] + pub record_batch: ::prost::alloc::vec::Vec, +} +#[derive(Clone, Copy, PartialEq, ::prost::Message)] +pub struct ListRecordingsRequest {} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ListRecordingsResponse { + #[prost(message, repeated, tag = "1")] + pub recordings: ::prost::alloc::vec::Vec, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct RecordingInfo { + #[prost(message, optional, tag = "1")] + pub id: ::core::option::Option, + #[prost(string, tag = "2")] + pub description: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub storage_url: ::prost::alloc::string::String, + #[prost(uint64, tag = "4")] + pub size_bytes: u64, + #[prost(enumeration = "RecordingType", tag = "5")] + pub typ: i32, +} +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum RecordingType { + Rrd = 0, +} +impl RecordingType { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Rrd => "RRD", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "RRD" => Some(Self::Rrd), + _ => None, + } + } +} +/// Generated client implementations. +pub mod storage_node_client { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value + )] + use tonic::codegen::http::Uri; + use tonic::codegen::*; + #[derive(Debug, Clone)] + pub struct StorageNodeClient { + inner: tonic::client::Grpc, + } + impl StorageNodeClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl StorageNodeClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + std::marker::Send + 'static, + ::Error: Into + std::marker::Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> StorageNodeClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + >>::Error: + Into + std::marker::Send + std::marker::Sync, + { + StorageNodeClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_decoding_message_size(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.inner = self.inner.max_encoding_message_size(limit); + self + } + pub async fn list_recordings( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rerun.remote_store.v0.StorageNode/ListRecordings", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "rerun.remote_store.v0.StorageNode", + "ListRecordings", + )); + self.inner.unary(req, path, codec).await + } + pub async fn query( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response>, + tonic::Status, + > { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = + http::uri::PathAndQuery::from_static("/rerun.remote_store.v0.StorageNode/Query"); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "rerun.remote_store.v0.StorageNode", + "Query", + )); + self.inner.server_streaming(req, path, codec).await + } + pub async fn get_recording_metadata( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rerun.remote_store.v0.StorageNode/GetRecordingMetadata", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "rerun.remote_store.v0.StorageNode", + "GetRecordingMetadata", + )); + self.inner.unary(req, path, codec).await + } + /// TODO (zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings + pub async fn register_recordings( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result, tonic::Status> + { + self.inner.ready().await.map_err(|e| { + tonic::Status::unknown(format!("Service was not ready: {}", e.into())) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/rerun.remote_store.v0.StorageNode/RegisterRecordings", + ); + let mut req = request.into_request(); + req.extensions_mut().insert(GrpcMethod::new( + "rerun.remote_store.v0.StorageNode", + "RegisterRecordings", + )); + self.inner.unary(req, path, codec).await + } + } +} +/// Generated server implementations. +pub mod storage_node_server { + #![allow( + unused_variables, + dead_code, + missing_docs, + clippy::wildcard_imports, + clippy::let_unit_value + )] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with StorageNodeServer. + #[async_trait] + pub trait StorageNode: std::marker::Send + std::marker::Sync + 'static { + async fn list_recordings( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// Server streaming response type for the Query method. + type QueryStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + std::marker::Send + + 'static; + async fn query( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + async fn get_recording_metadata( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + /// TODO (zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings + async fn register_recordings( + &self, + request: tonic::Request, + ) -> std::result::Result, tonic::Status>; + } + #[derive(Debug)] + pub struct StorageNodeServer { + inner: Arc, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + max_decoding_message_size: Option, + max_encoding_message_size: Option, + } + impl StorageNodeServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + max_decoding_message_size: None, + max_encoding_message_size: None, + } + } + pub fn with_interceptor(inner: T, interceptor: F) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + /// Limits the maximum size of a decoded message. + /// + /// Default: `4MB` + #[must_use] + pub fn max_decoding_message_size(mut self, limit: usize) -> Self { + self.max_decoding_message_size = Some(limit); + self + } + /// Limits the maximum size of an encoded message. + /// + /// Default: `usize::MAX` + #[must_use] + pub fn max_encoding_message_size(mut self, limit: usize) -> Self { + self.max_encoding_message_size = Some(limit); + self + } + } + impl tonic::codegen::Service> for StorageNodeServer + where + T: StorageNode, + B: Body + std::marker::Send + 'static, + B::Error: Into + std::marker::Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + match req.uri().path() { + "/rerun.remote_store.v0.StorageNode/ListRecordings" => { + #[allow(non_camel_case_types)] + struct ListRecordingsSvc(pub Arc); + impl tonic::server::UnaryService + for ListRecordingsSvc + { + type Response = super::ListRecordingsResponse; + type Future = BoxFuture, tonic::Status>; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::list_recordings(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = ListRecordingsSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/rerun.remote_store.v0.StorageNode/Query" => { + #[allow(non_camel_case_types)] + struct QuerySvc(pub Arc); + impl tonic::server::ServerStreamingService for QuerySvc { + type Response = super::QueryResponse; + type ResponseStream = T::QueryStream; + type Future = + BoxFuture, tonic::Status>; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = + async move { ::query(&inner, request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = QuerySvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.server_streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/rerun.remote_store.v0.StorageNode/GetRecordingMetadata" => { + #[allow(non_camel_case_types)] + struct GetRecordingMetadataSvc(pub Arc); + impl + tonic::server::UnaryService + for GetRecordingMetadataSvc + { + type Response = super::GetRecordingMetadataResponse; + type Future = BoxFuture, tonic::Status>; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::get_recording_metadata(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = GetRecordingMetadataSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/rerun.remote_store.v0.StorageNode/RegisterRecordings" => { + #[allow(non_camel_case_types)] + struct RegisterRecordingsSvc(pub Arc); + impl + tonic::server::UnaryService + for RegisterRecordingsSvc + { + type Response = super::RegisterRecordingsResponse; + type Future = BoxFuture, tonic::Status>; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::register_recordings(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = RegisterRecordingsSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => Box::pin(async move { + let mut response = http::Response::new(empty_body()); + let headers = response.headers_mut(); + headers.insert( + tonic::Status::GRPC_STATUS, + (tonic::Code::Unimplemented as i32).into(), + ); + headers.insert( + http::header::CONTENT_TYPE, + tonic::metadata::GRPC_CONTENT_TYPE, + ); + Ok(response) + }), + } + } + } + impl Clone for StorageNodeServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + max_decoding_message_size: self.max_decoding_message_size, + max_encoding_message_size: self.max_encoding_message_size, + } + } + } + /// Generated gRPC service name + pub const SERVICE_NAME: &str = "rerun.remote_store.v0.StorageNode"; + impl tonic::server::NamedService for StorageNodeServer { + const NAME: &'static str = SERVICE_NAME; + } +} diff --git a/crates/store/re_ws_comms/src/client.rs b/crates/store/re_ws_comms/src/client.rs index 7d793fc9648c..e3bb9568dde7 100644 --- a/crates/store/re_ws_comms/src/client.rs +++ b/crates/store/re_ws_comms/src/client.rs @@ -1,4 +1,4 @@ -use std::ops::ControlFlow; +use std::{ops::ControlFlow, time::Duration}; use ewebsock::{WsEvent, WsMessage}; @@ -16,6 +16,7 @@ pub fn viewer_to_server( // We set a very high limit, because we should be able to trust the server. // See https://github.com/rerun-io/rerun/issues/5268 for more max_incoming_frame_size: 2 * gigs, + delay_blocking: Duration::from_millis(10), }; ewebsock::ws_receive( diff --git a/deny.toml b/deny.toml index 2e1166e5f5e7..6ab927c09aec 100644 --- a/deny.toml +++ b/deny.toml @@ -61,7 +61,6 @@ skip = [ { name = "raw-window-handle" }, # Pretty small crate; some crates still on old version { name = "redox_syscall" }, # Plenty of versions in the wild { name = "spin" }, # Old version used by rusttls - { name = "webpki-roots" }, # ureq and tungstenite are on different version 😭 ] skip-tree = [ { name = "async-io" }, # Old version via rfd @@ -72,6 +71,7 @@ skip-tree = [ { name = "prost-derive" }, # only used in objectron example { name = "toml_edit" }, # Old version via egui-winit, newer used by rustdoc-json { name = "windows" }, # Old version used by accesskit_windows, newer version used by wgpu + { name = "tower" }, # tonic depends on 0.4.3, but also transitively (axum) on 0.5.1 ] diff --git a/pixi.toml b/pixi.toml index 56ab2208126c..019453bab53c 100644 --- a/pixi.toml +++ b/pixi.toml @@ -114,6 +114,9 @@ examples-pypi = ["examples-common", "python-pypi"] # Run the codegen. Optionally pass `--profile` argument if you want. codegen = "cargo --quiet run --package re_types_builder -- " +# Run the codegen for remote store types. +codegen-rstore = "cargo --quiet run --package re_remote_store_types_builder -- " + # Generate the Rerun CLI manual. # NOTE:must be --all-features, otherwise we might miss some optional commands. diff --git a/scripts/lint.py b/scripts/lint.py index ce9a83ec8392..5926bc3c0dc1 100755 --- a/scripts/lint.py +++ b/scripts/lint.py @@ -1181,6 +1181,7 @@ def main() -> None: "./.pytest_cache", "./CODE_STYLE.md", "./crates/build/re_types_builder/src/reflection.rs", # auto-generated + "./crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs", # auto-generated "./docs/content/reference/cli.md", # auto-generated "./examples/assets", "./examples/python/detect_and_track_objects/cache/version.txt", From 2bab7c6b11a10a570343ed0df4d3dd314b6bb960 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:26:35 +0200 Subject: [PATCH 25/33] remove unused deps (thanks machete) --- Cargo.lock | 5 ----- crates/build/re_remote_store_types_builder/Cargo.toml | 4 ---- crates/store/re_remote_store_types/Cargo.toml | 1 - 3 files changed, 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1cd9c25fdcee..19fbe78dfa1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5623,7 +5623,6 @@ dependencies = [ "re_log_types", "thiserror", "tonic", - "tonic-build", ] [[package]] @@ -5631,11 +5630,7 @@ name = "re_remote_store_types_builder" version = "0.19.0-alpha.1+dev" dependencies = [ "camino", - "re_dataframe", "re_log", - "re_log_types", - "re_tracing", - "tonic", "tonic-build", ] diff --git a/crates/build/re_remote_store_types_builder/Cargo.toml b/crates/build/re_remote_store_types_builder/Cargo.toml index 348173742ed2..f104efa1caa0 100644 --- a/crates/build/re_remote_store_types_builder/Cargo.toml +++ b/crates/build/re_remote_store_types_builder/Cargo.toml @@ -12,14 +12,10 @@ version.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -re_dataframe.workspace = true re_log = { workspace = true, features = ["setup"] } -re_log_types.workspace = true -re_tracing = { workspace = true, features = ["server"] } # External camino.workspace = true -tonic.workspace = true tonic-build.workspace = true [lints] diff --git a/crates/store/re_remote_store_types/Cargo.toml b/crates/store/re_remote_store_types/Cargo.toml index 5db04a5a089a..933745526dfb 100644 --- a/crates/store/re_remote_store_types/Cargo.toml +++ b/crates/store/re_remote_store_types/Cargo.toml @@ -17,7 +17,6 @@ re_dataframe.workspace = true prost.workspace = true thiserror.workspace = true tonic.workspace = true -tonic-build.workspace = true [lints] workspace = true From b2af3b103f782319ca78fc8d2da5ca951cd88a67 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:01:33 +0200 Subject: [PATCH 26/33] add a simple unit test for query expression conversion --- crates/store/re_remote_store_types/src/lib.rs | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/crates/store/re_remote_store_types/src/lib.rs b/crates/store/re_remote_store_types/src/lib.rs index f1a327ae94fd..8d46755a67ec 100644 --- a/crates/store/re_remote_store_types/src/lib.rs +++ b/crates/store/re_remote_store_types/src/lib.rs @@ -215,3 +215,125 @@ pub mod v0 { } } } + +#[cfg(test)] +mod tests { + use std::collections::{BTreeMap, BTreeSet}; + + use crate::v0::{ + column_selector::SelectorType, ColumnSelection, ColumnSelector, Component, + ComponentColumnSelector, ComponentsSet, EntityPath, IndexColumnSelector, IndexRange, + IndexValues, Query, SparseFillStrategy, TimeInt, TimeRange, Timeline, ViewContents, + ViewContentsPart, + }; + + #[test] + pub fn test_query_conversion() { + // from grpc type... + let query = Query { + view_contents: Some(ViewContents { + contents: vec![ViewContentsPart { + path: Some(EntityPath { + path: "/somepath".to_owned(), + }), + components: Some(ComponentsSet { + components: vec![Component { + name: "component".to_owned(), + }], + }), + }], + }), + filtered_index: Some(IndexColumnSelector { + timeline: Some(Timeline { + name: "log_time".to_owned(), + }), + }), + filtered_index_range: Some(IndexRange { + time_range: Some(TimeRange { start: 0, end: 100 }), + }), + filtered_index_values: Some(IndexValues { + time_points: vec![ + TimeInt { time: 0 }, + TimeInt { time: 1 }, + TimeInt { time: 2 }, + ], + }), + using_index_values: Some(IndexValues { + time_points: vec![ + TimeInt { time: 3 }, + TimeInt { time: 4 }, + TimeInt { time: 5 }, + ], + }), + filtered_pov: Some(ComponentColumnSelector { + entity_path: Some(EntityPath { + path: "/somepath/c".to_owned(), + }), + component: Some(Component { + name: "component".to_owned(), + }), + }), + column_selection: Some(ColumnSelection { + columns: vec![ColumnSelector { + selector_type: Some(SelectorType::ComponentColumn(ComponentColumnSelector { + entity_path: Some(EntityPath { + path: "/somepath/c".to_owned(), + }), + component: Some(Component { + name: "component".to_owned(), + }), + })), + }], + }), + sparse_fill_strategy: SparseFillStrategy::None.into(), + }; + + // ...to chunk store query expression + let expected_qe = re_dataframe::external::re_chunk_store::QueryExpression { + view_contents: Some(BTreeMap::from([( + re_log_types::EntityPath::from("/somepath"), + Some(BTreeSet::from([ + re_dataframe::external::re_chunk::ComponentName::new("component"), + ])), + )])), + filtered_index: re_log_types::Timeline::new_temporal("log_time"), + filtered_index_range: Some(re_dataframe::external::re_chunk_store::IndexRange::new( + 0, 100, + )), + filtered_index_values: Some( + vec![0, 1, 2] + .into_iter() + .map(re_log_types::TimeInt::new_temporal) + .collect::>(), + ), + using_index_values: Some( + vec![3, 4, 5] + .into_iter() + .map(re_log_types::TimeInt::new_temporal) + .collect::>(), + ), + filtered_point_of_view: Some( + re_dataframe::external::re_chunk_store::ComponentColumnSelector { + entity_path: re_log_types::EntityPath::from("/somepath/c"), + component: re_dataframe::external::re_chunk::ComponentName::new("component"), + join_encoding: re_dataframe::external::re_chunk_store::JoinEncoding::default(), + }, + ), + sparse_fill_strategy: + re_dataframe::external::re_chunk_store::SparseFillStrategy::default(), + selection: Some(vec![ + re_dataframe::external::re_chunk_store::ComponentColumnSelector { + entity_path: re_log_types::EntityPath::from("/somepath/c"), + component: re_dataframe::external::re_chunk::ComponentName::new("component"), + join_encoding: re_dataframe::external::re_chunk_store::JoinEncoding::default(), + } + .into(), + ]), + }; + + let query_expression: re_dataframe::external::re_chunk_store::QueryExpression = + query.try_into().unwrap(); + + assert_eq!(query_expression, expected_qe); + } +} From ac2b680caa8f333f385cd0e52a80be9d3e42dcbc Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:06:35 +0200 Subject: [PATCH 27/33] linter fix --- crates/store/re_remote_store_types/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/store/re_remote_store_types/src/lib.rs b/crates/store/re_remote_store_types/src/lib.rs index 8d46755a67ec..caa4f4705fea 100644 --- a/crates/store/re_remote_store_types/src/lib.rs +++ b/crates/store/re_remote_store_types/src/lib.rs @@ -229,7 +229,7 @@ mod tests { #[test] pub fn test_query_conversion() { - // from grpc type... + // from grpc type let query = Query { view_contents: Some(ViewContents { contents: vec![ViewContentsPart { @@ -288,7 +288,7 @@ mod tests { sparse_fill_strategy: SparseFillStrategy::None.into(), }; - // ...to chunk store query expression + // to chunk store query expression let expected_qe = re_dataframe::external::re_chunk_store::QueryExpression { view_contents: Some(BTreeMap::from([( re_log_types::EntityPath::from("/somepath"), From 04bb81a69307c451f8dbb30b2dd61134b08d6492 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Thu, 10 Oct 2024 15:13:45 +0200 Subject: [PATCH 28/33] use ewebsock 0.7.0 --- Cargo.lock | 5 +++-- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19fbe78dfa1f..a5d7613e784b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2337,8 +2337,9 @@ dependencies = [ [[package]] name = "ewebsock" -version = "0.6.0" -source = "git+https://github.com/rerun-io/ewebsock?rev=1a9e78aa18390511476f9e2c0453502f11a7aa78#1a9e78aa18390511476f9e2c0453502f11a7aa78" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "735ef60c8cd338b55f972d66c95558a71298d6f8bce1e1347d4c95b082ab2c37" dependencies = [ "document-features", "js-sys", diff --git a/Cargo.toml b/Cargo.toml index a3bd3b3a8851..7f41f755b419 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,7 +105,7 @@ re_viewport_blueprint = { path = "crates/viewer/re_viewport_blueprint", version re_web_viewer_server = { path = "crates/viewer/re_web_viewer_server", version = "=0.19.0-alpha.3", default-features = false } # Rerun crates in other repos: -ewebsock = { git = "https://github.com/rerun-io/ewebsock", rev = "1a9e78aa18390511476f9e2c0453502f11a7aa78" } +ewebsock = "0.7.0" re_math = "0.20.0" # egui-crates: From c9f65b5d08f78969787c08ea5cc1b05e859fb871 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Mon, 14 Oct 2024 08:25:54 +0200 Subject: [PATCH 29/33] rebase --- Cargo.lock | 4 ++-- crates/build/README.md | 13 +------------ 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a5d7613e784b..ae755e61149f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5617,7 +5617,7 @@ dependencies = [ [[package]] name = "re_remote_store_types" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.3" dependencies = [ "prost 0.13.3", "re_dataframe", @@ -5628,7 +5628,7 @@ dependencies = [ [[package]] name = "re_remote_store_types_builder" -version = "0.19.0-alpha.1+dev" +version = "0.19.0-alpha.3" dependencies = [ "camino", "re_log", diff --git a/crates/build/README.md b/crates/build/README.md index 615f8490ad09..8e09a075d66f 100644 --- a/crates/build/README.md +++ b/crates/build/README.md @@ -1,12 +1 @@ -# re_remote_store_types_builder - -Part of the [`rerun`](https://github.com/rerun-io/rerun) family of crates. - -[![Latest version](https://img.shields.io/crates/v/re_remote_store_types_builder.svg)](https://crates.io/crates/re_remote_store_types_builder) -[![Documentation](https://docs.rs/re_remote_store_types_builder/badge.svg)](https://docs.rs/re_remote_store_types_builder) -![MIT](https://img.shields.io/badge/license-MIT-blue.svg) -![Apache](https://img.shields.io/badge/license-Apache-blue.svg) - -This crate implements Rerun's code generation for the remote store node gRPC API definition. - -You can generate the code with `pixi run codegen-rstore`. +Crates run at build-time From c88577b8e7a27dac8c90164002d4f7889926541e Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Mon, 14 Oct 2024 08:37:15 +0200 Subject: [PATCH 30/33] address comments - part1 --- .../src/bin/build_re_remote_store_types.rs | 7 ++++++- .../proto/rerun/v0/common.proto | 7 +++---- .../proto/rerun/v0/remote_store.proto | 6 +++--- crates/store/re_remote_store_types/src/lib.rs | 14 +++++++------- .../src/v0/rerun.remote_store.v0.rs | 15 +++++++-------- 5 files changed, 26 insertions(+), 23 deletions(-) diff --git a/crates/build/re_remote_store_types_builder/src/bin/build_re_remote_store_types.rs b/crates/build/re_remote_store_types_builder/src/bin/build_re_remote_store_types.rs index f70dc0cca261..3f6d884da31b 100644 --- a/crates/build/re_remote_store_types_builder/src/bin/build_re_remote_store_types.rs +++ b/crates/build/re_remote_store_types_builder/src/bin/build_re_remote_store_types.rs @@ -20,6 +20,7 @@ fn main() { .and_then(|p| p.parent()) .unwrap(); + // Check for something that only exists in root: assert!( workspace_dir.join("CODE_OF_CONDUCT.md").exists(), "failed to find workspace root" @@ -28,7 +29,11 @@ fn main() { let definitions_dir_path = workspace_dir.join(PROTOBUF_DEFINITIONS_DIR_PATH); let rust_generated_output_dir_path = workspace_dir.join(RUST_V0_OUTPUT_DIR_PATH); - re_log::info!("Running codegen for storage node types"); + re_log::info!( + definitions=?definitions_dir_path, + output=?rust_generated_output_dir_path, + "Running codegen for storage node types", + ); re_remote_store_types_builder::generate_rust_code( definitions_dir_path, diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto index 072cff95f2a5..47d34f41f23a 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto @@ -57,17 +57,17 @@ message ColumnSelector { } message IndexColumnSelector { - // TODO (zehiko) we need to add support for other types of index selectors + // TODO(zehiko) we need to add support for other types of index selectors Timeline timeline = 1; } message IndexRange { - // TODO (zehiko) support for other ranges for other index selectors + // TODO(zehiko) support for other ranges for other index selectors TimeRange time_range = 1; } message IndexValues { - // TODO (zehiko) we need to add support for other types of index selectors + // TODO(zehiko) we need to add support for other types of index selectors repeated TimeInt time_points = 1; } @@ -108,7 +108,6 @@ message TimeColumnSelector { message ComponentColumnSelector { EntityPath entity_path = 1; Component component = 2; - // TODO do we need join encoding? } enum SparseFillStrategy { diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto index 8be53c1a0ffe..55822e1fbd37 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/remote_store.proto @@ -8,7 +8,7 @@ service StorageNode { rpc ListRecordings(ListRecordingsRequest) returns (ListRecordingsResponse) {} rpc Query(QueryRequest) returns (stream QueryResponse) {} rpc GetRecordingMetadata(GetRecordingMetadataRequest) returns (GetRecordingMetadataResponse) {} - // TODO (zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings + // TODO(zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings rpc RegisterRecordings(RegisterRecordingsRequest) returns (RegisterRecordingsResponse) {} } @@ -17,7 +17,7 @@ service StorageNode { message RegisterRecordingsRequest { string description = 1; ObjectStorage obj_storage = 2; - // TODO (zehiko) should this be auto-discoverable? + // TODO(zehiko) should this be auto-discoverable? RecordingType typ = 3; } @@ -27,7 +27,7 @@ message ObjectStorage { } message RegisterRecordingsResponse { - // Note / TODO (zehiko): this implies we read the record (for example go through entire .rrd file + // Note / TODO(zehiko): this implies we read the record (for example go through entire .rrd file // chunk by chunk) and extract the metadata. So we might want to 1/ not do this i.e. // only do it as part of explicit GetMetadata request or 2/ do it if Request has "include_metadata=true" // or 3/ do it always diff --git a/crates/store/re_remote_store_types/src/lib.rs b/crates/store/re_remote_store_types/src/lib.rs index caa4f4705fea..5dcde7783723 100644 --- a/crates/store/re_remote_store_types/src/lib.rs +++ b/crates/store/re_remote_store_types/src/lib.rs @@ -6,15 +6,15 @@ //! necessary conversion code (in the form of `From` and `TryFrom` traits) in this crate. //! -// Ignoring all warnings for the auto-generated code. -#![allow(clippy::doc_markdown)] -#![allow(clippy::derive_partial_eq_without_eq)] -#![allow(clippy::enum_variant_names)] -#![allow(clippy::unwrap_used)] -#![allow(clippy::wildcard_imports)] -#![allow(clippy::manual_is_variant_and)] /// Generated types for the remote store gRPC service API v0. pub mod v0 { + // Ignoring all warnings for the auto-generated code. + #![allow(clippy::doc_markdown)] + #![allow(clippy::derive_partial_eq_without_eq)] + #![allow(clippy::enum_variant_names)] + #![allow(clippy::unwrap_used)] + #![allow(clippy::wildcard_imports)] + #![allow(clippy::manual_is_variant_and)] #[path = "../v0/rerun.remote_store.v0.rs"] mod _v0; diff --git a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs index 8ba9fadd7e2a..e4c4665cf1b9 100644 --- a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs +++ b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs @@ -77,19 +77,19 @@ pub mod column_selector { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct IndexColumnSelector { - /// TODO (zehiko) we need to add support for other types of index selectors + /// TODO(zehiko) we need to add support for other types of index selectors #[prost(message, optional, tag = "1")] pub timeline: ::core::option::Option, } #[derive(Clone, Copy, PartialEq, ::prost::Message)] pub struct IndexRange { - /// TODO (zehiko) support for other ranges for other index selectors + /// TODO(zehiko) support for other ranges for other index selectors #[prost(message, optional, tag = "1")] pub time_range: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct IndexValues { - /// TODO (zehiko) we need to add support for other types of index selectors + /// TODO(zehiko) we need to add support for other types of index selectors #[prost(message, repeated, tag = "1")] pub time_points: ::prost::alloc::vec::Vec, } @@ -140,7 +140,6 @@ pub struct TimeColumnSelector { pub struct ComponentColumnSelector { #[prost(message, optional, tag = "1")] pub entity_path: ::core::option::Option, - /// TODO do we need join encoding? #[prost(message, optional, tag = "2")] pub component: ::core::option::Option, } @@ -176,7 +175,7 @@ pub struct RegisterRecordingsRequest { pub description: ::prost::alloc::string::String, #[prost(message, optional, tag = "2")] pub obj_storage: ::core::option::Option, - /// TODO (zehiko) should this be auto-discoverable? + /// TODO(zehiko) should this be auto-discoverable? #[prost(enumeration = "RecordingType", tag = "3")] pub typ: i32, } @@ -189,7 +188,7 @@ pub struct ObjectStorage { } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RegisterRecordingsResponse { - /// Note / TODO (zehiko): this implies we read the record (for example go through entire .rrd file + /// Note / TODO(zehiko): this implies we read the record (for example go through entire .rrd file /// chunk by chunk) and extract the metadata. So we might want to 1/ not do this i.e. /// only do it as part of explicit GetMetadata request or 2/ do it if Request has "include_metadata=true" /// or 3/ do it always @@ -428,7 +427,7 @@ pub mod storage_node_client { )); self.inner.unary(req, path, codec).await } - /// TODO (zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings + /// TODO(zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings pub async fn register_recordings( &mut self, request: impl tonic::IntoRequest, @@ -480,7 +479,7 @@ pub mod storage_node_server { &self, request: tonic::Request, ) -> std::result::Result, tonic::Status>; - /// TODO (zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings + /// TODO(zehiko) - should this be singular recording registration? Currently we can have 1 rrd => many recordings async fn register_recordings( &self, request: tonic::Request, From 5fa0d8a1312dcf26a5ddb66738facc5b80106773 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Mon, 14 Oct 2024 08:58:36 +0200 Subject: [PATCH 31/33] rebase - part2 (fix rebase) --- .../proto/rerun/v0/common.proto | 20 ++++++++++------ crates/store/re_remote_store_types/src/lib.rs | 21 ++++++++++++----- .../src/v0/rerun.remote_store.v0.rs | 23 +++++++++++++------ 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto index 47d34f41f23a..bfbd1e328298 100644 --- a/crates/store/re_remote_store_types/proto/rerun/v0/common.proto +++ b/crates/store/re_remote_store_types/proto/rerun/v0/common.proto @@ -27,22 +27,28 @@ message Schema { message Query { // database view defined by entity paths and components ViewContents view_contents = 1; + // define whethere the view_contents should include semantically empty columns + bool include_semantically_empty_columns = 2; + // define whether the view_contents should ignore columns corresponding to indicator components + bool include_indicator_columns = 3; + // define whether the view_contents should ignore columns corresponding to `Clear`-related components. + bool include_tombstone_columns = 4; // filtering index (just a string i.e. a name of the timeline for starters) - IndexColumnSelector filtered_index = 2; + IndexColumnSelector filtered_index = 5; // Optional specific range for the index selector - IndexRange filtered_index_range = 3; + IndexRange filtered_index_range = 6; // Optional specific values for the index selector - IndexValues filtered_index_values = 4; + IndexValues filtered_index_values = 7; // Optional index selector sampling - IndexValues using_index_values = 5; + IndexValues using_index_values = 8; // PoV (filtering) component - ComponentColumnSelector filtered_pov = 6; + ComponentColumnSelector filtered_pov = 9; // which columns to include in the response // Note - we have one more layer of indiraction to ensure the field is optional, // same as in the query expression. We can't have both 'repeated' and 'optional' field labels. - ColumnSelection column_selection = 7; + ColumnSelection column_selection = 10; // how are null values filled in the response - SparseFillStrategy sparse_fill_strategy = 8; + SparseFillStrategy sparse_fill_strategy = 11; } message ColumnSelection { diff --git a/crates/store/re_remote_store_types/src/lib.rs b/crates/store/re_remote_store_types/src/lib.rs index 5dcde7783723..b67c12333f0c 100644 --- a/crates/store/re_remote_store_types/src/lib.rs +++ b/crates/store/re_remote_store_types/src/lib.rs @@ -69,7 +69,10 @@ pub mod v0 { Ok(Self { view_contents: value.view_contents.map(|vc| vc.into()), - filtered_index, + include_semantically_empty_columns: value.include_semantically_empty_columns, + include_indicator_columns: value.include_indicator_columns, + include_tombstone_columns: value.include_tombstone_columns, + filtered_index: Some(filtered_index), filtered_index_range: value .filtered_index_range .map(|ir| ir.try_into()) @@ -165,14 +168,14 @@ pub mod v0 { .ok_or(TypeConversionError::MissingField("entity_path"))? .into(); - let component = value + let component_name = value .component .ok_or(TypeConversionError::MissingField("component"))? .name; Ok(Self { entity_path, - component: re_dataframe::external::re_chunk::ComponentName::new(&component), + component_name, join_encoding: re_dataframe::external::re_chunk_store::JoinEncoding::default(), // TODO(zehiko) implement }) } @@ -243,6 +246,9 @@ mod tests { }), }], }), + include_indicator_columns: false, + include_semantically_empty_columns: true, + include_tombstone_columns: true, filtered_index: Some(IndexColumnSelector { timeline: Some(Timeline { name: "log_time".to_owned(), @@ -296,7 +302,10 @@ mod tests { re_dataframe::external::re_chunk::ComponentName::new("component"), ])), )])), - filtered_index: re_log_types::Timeline::new_temporal("log_time"), + include_indicator_columns: false, + include_semantically_empty_columns: true, + include_tombstone_columns: true, + filtered_index: Some(re_log_types::Timeline::new_temporal("log_time")), filtered_index_range: Some(re_dataframe::external::re_chunk_store::IndexRange::new( 0, 100, )), @@ -315,7 +324,7 @@ mod tests { filtered_point_of_view: Some( re_dataframe::external::re_chunk_store::ComponentColumnSelector { entity_path: re_log_types::EntityPath::from("/somepath/c"), - component: re_dataframe::external::re_chunk::ComponentName::new("component"), + component_name: "component".to_owned(), join_encoding: re_dataframe::external::re_chunk_store::JoinEncoding::default(), }, ), @@ -324,7 +333,7 @@ mod tests { selection: Some(vec![ re_dataframe::external::re_chunk_store::ComponentColumnSelector { entity_path: re_log_types::EntityPath::from("/somepath/c"), - component: re_dataframe::external::re_chunk::ComponentName::new("component"), + component_name: "component".to_owned(), join_encoding: re_dataframe::external::re_chunk_store::JoinEncoding::default(), } .into(), diff --git a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs index e4c4665cf1b9..6ad626cebecc 100644 --- a/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs +++ b/crates/store/re_remote_store_types/src/v0/rerun.remote_store.v0.rs @@ -31,28 +31,37 @@ pub struct Query { /// database view defined by entity paths and components #[prost(message, optional, tag = "1")] pub view_contents: ::core::option::Option, + /// define whethere the view_contents should include semantically empty columns + #[prost(bool, tag = "2")] + pub include_semantically_empty_columns: bool, + /// define whether the view_contents should ignore columns corresponding to indicator components + #[prost(bool, tag = "3")] + pub include_indicator_columns: bool, + /// define whether the view_contents should ignore columns corresponding to `Clear`-related components. + #[prost(bool, tag = "4")] + pub include_tombstone_columns: bool, /// filtering index (just a string i.e. a name of the timeline for starters) - #[prost(message, optional, tag = "2")] + #[prost(message, optional, tag = "5")] pub filtered_index: ::core::option::Option, /// Optional specific range for the index selector - #[prost(message, optional, tag = "3")] + #[prost(message, optional, tag = "6")] pub filtered_index_range: ::core::option::Option, /// Optional specific values for the index selector - #[prost(message, optional, tag = "4")] + #[prost(message, optional, tag = "7")] pub filtered_index_values: ::core::option::Option, /// Optional index selector sampling - #[prost(message, optional, tag = "5")] + #[prost(message, optional, tag = "8")] pub using_index_values: ::core::option::Option, /// PoV (filtering) component - #[prost(message, optional, tag = "6")] + #[prost(message, optional, tag = "9")] pub filtered_pov: ::core::option::Option, /// which columns to include in the response /// Note - we have one more layer of indiraction to ensure the field is optional, /// same as in the query expression. We can't have both 'repeated' and 'optional' field labels. - #[prost(message, optional, tag = "7")] + #[prost(message, optional, tag = "10")] pub column_selection: ::core::option::Option, /// how are null values filled in the response - #[prost(enumeration = "SparseFillStrategy", tag = "8")] + #[prost(enumeration = "SparseFillStrategy", tag = "11")] pub sparse_fill_strategy: i32, } #[derive(Clone, PartialEq, ::prost::Message)] From 4203b97521a7e4874ec9b1d90ffc9ec82d231799 Mon Sep 17 00:00:00 2001 From: Clement Rey Date: Fri, 11 Oct 2024 10:07:14 +0200 Subject: [PATCH 32/33] prost_build gotta chill man --- crates/utils/re_log/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/utils/re_log/src/lib.rs b/crates/utils/re_log/src/lib.rs index 195a984e5a3f..7befc2d8515c 100644 --- a/crates/utils/re_log/src/lib.rs +++ b/crates/utils/re_log/src/lib.rs @@ -72,6 +72,7 @@ const CRATES_AT_INFO_LEVEL: &[&str] = &[ // These are quite spammy on debug, drowning out what we care about: "h2", "hyper", + "prost_build", "ureq", // only let rustls log in debug mode: https://github.com/rerun-io/rerun/issues/3104 #[cfg(debug_assertions)] From abfb88754ee61b67c097e6e7a07c6504e07c9387 Mon Sep 17 00:00:00 2001 From: Zeljko Mihaljcic <7150613+zehiko@users.noreply.github.com> Date: Mon, 14 Oct 2024 09:15:21 +0200 Subject: [PATCH 33/33] small fixes --- crates/store/re_remote_store_types/src/lib.rs | 1 + crates/store/re_ws_comms/src/client.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/store/re_remote_store_types/src/lib.rs b/crates/store/re_remote_store_types/src/lib.rs index b67c12333f0c..30b0940ed167 100644 --- a/crates/store/re_remote_store_types/src/lib.rs +++ b/crates/store/re_remote_store_types/src/lib.rs @@ -126,6 +126,7 @@ pub mod v0 { .ok_or(TypeConversionError::MissingField("timeline"))? .name; + // TODO(cmc): QueryExpression::filtered_index gotta be a selector #[allow(clippy::match_same_arms)] let timeline = match timeline_name.as_str() { "log_time" => Self::new_temporal(timeline_name), diff --git a/crates/store/re_ws_comms/src/client.rs b/crates/store/re_ws_comms/src/client.rs index e3bb9568dde7..6fa617f90023 100644 --- a/crates/store/re_ws_comms/src/client.rs +++ b/crates/store/re_ws_comms/src/client.rs @@ -1,4 +1,4 @@ -use std::{ops::ControlFlow, time::Duration}; +use std::ops::ControlFlow; use ewebsock::{WsEvent, WsMessage}; @@ -16,7 +16,7 @@ pub fn viewer_to_server( // We set a very high limit, because we should be able to trust the server. // See https://github.com/rerun-io/rerun/issues/5268 for more max_incoming_frame_size: 2 * gigs, - delay_blocking: Duration::from_millis(10), + ..ewebsock::Options::default() }; ewebsock::ws_receive(