diff --git a/crates/build/re_types_builder/src/codegen/python/mod.rs b/crates/build/re_types_builder/src/codegen/python/mod.rs index e85f2d38efab..62ddf04f2553 100644 --- a/crates/build/re_types_builder/src/codegen/python/mod.rs +++ b/crates/build/re_types_builder/src/codegen/python/mod.rs @@ -2649,8 +2649,8 @@ fn quote_columnar_methods(reporter: &Reporter, obj: &Object, objects: &Objects) for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/docs/content/howto/logging/send-columns.md b/docs/content/howto/logging/send-columns.md index 335a45a83a91..d28c40b1caba 100644 --- a/docs/content/howto/logging/send-columns.md +++ b/docs/content/howto/logging/send-columns.md @@ -63,9 +63,31 @@ snippet: archetypes/points3d_column_updates + Each row in the component column can be a batch of data, e.g. a batch of positions. This lets you log the evolution of a point cloud over time efficiently. +### Updating a fixed number of arrows over time, in a single operation + +Consider this snippet, using the row-oriented `log` API: + +snippet: archetypes/arrows3d_row_updates + +which can be translated to the column-oriented `send_columns` API as such: + +snippet: archetypes/arrows3d_column_updates + + + + + + + + + +Each row in the component column can be a batch of data, e.g. a batch of positions. +This lets you log the evolution of a set of arrows over time efficiently. + ### Updating a transform over time, in a single operation diff --git a/docs/snippets/INDEX.md b/docs/snippets/INDEX.md index b2ca2997c4bf..93fbf36ded31 100644 --- a/docs/snippets/INDEX.md +++ b/docs/snippets/INDEX.md @@ -20,6 +20,7 @@ Use it to quickly find copy-pastable snippets of code for any Rerun feature you' | Feature | Example | Description | Python | Rust | C+⁠+ | | ------- | ------- | ----------- | :----: | :--: | :-------: | +| **Update rows** | `arrows3d_row_updates` | Update a set of vectors over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.cpp) | | **Update rows** | `scalar_row_updates` | Update a scalar over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/scalar_row_updates.cpp) | | **Update rows** | `points3d_row_updates` | Update a point cloud over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_row_updates.cpp) | | **Update rows** | `transform3d_row_updates` | Update a transform over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_row_updates.cpp) | @@ -55,6 +56,8 @@ _All snippets, organized by the [`Archetype`](https://rerun.io/docs/reference/ty | **[`AnnotationContext`](https://rerun.io/docs/reference/types/archetypes/annotation_context)** | `archetypes⁠/⁠segmentation_image_simple` | Create and log a segmentation image | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/segmentation_image_simple.cpp) | | **[`Arrows2D`](https://rerun.io/docs/reference/types/archetypes/arrows2d)** | `archetypes⁠/⁠arrows2d_simple` | Log a batch of 2D arrows | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows2d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows2d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows2d_simple.cpp) | | **[`Arrows3D`](https://rerun.io/docs/reference/types/archetypes/arrows3d)** | `archetypes⁠/⁠arrows3d_simple` | Log a batch of 3D arrows | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_simple.cpp) | +| **[`Arrows3D`](https://rerun.io/docs/reference/types/archetypes/arrows3d)** | `archetypes⁠/⁠arrows3d_row_updates` | Update a set of vectors over time | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.cpp) | +| **[`Arrows3D`](https://rerun.io/docs/reference/types/archetypes/arrows3d)** | `archetypes⁠/⁠arrows3d_column_updates` | Update a set of vectors over time, in a single operation | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_column_updates.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_column_updates.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_column_updates.cpp) | | **[`Arrows3D`](https://rerun.io/docs/reference/types/archetypes/arrows3d)** | `archetypes⁠/⁠clear_recursive` | Log and then clear data recursively | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_recursive.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_recursive.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_recursive.cpp) | | **[`Arrows3D`](https://rerun.io/docs/reference/types/archetypes/arrows3d)** | `archetypes⁠/⁠clear_simple` | Log and then clear data | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/clear_simple.cpp) | | **[`Arrows3D`](https://rerun.io/docs/reference/types/archetypes/arrows3d)** | `archetypes⁠/⁠transform3d_simple` | Log different transforms between three arrows | [🐍](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_simple.py) | [🦀](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_simple.rs) | [🌊](https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_simple.cpp) | diff --git a/docs/snippets/all/archetypes/arrows3d_column_updates.cpp b/docs/snippets/all/archetypes/arrows3d_column_updates.cpp new file mode 100644 index 000000000000..d2c78ad32a83 --- /dev/null +++ b/docs/snippets/all/archetypes/arrows3d_column_updates.cpp @@ -0,0 +1,52 @@ +// Update a set of vectors over time, in a single operation. +// +// This is semantically equivalent to the `arrows3d_row_updates` example, albeit much faster. + +#include +#include + +#include +#include + +using namespace std::chrono_literals; + +int main() { + const auto rec = rerun::RecordingStream("rerun_example_arrows3d_column_updates"); + rec.spawn().exit_on_failure(); + + // Prepare a fixed sequence of arrows over 5 timesteps. + // Origins stay constant, vectors change magnitude and direction, and each timestep has a unique color. + std::vector> origins; + std::vector> vectors; + + for (size_t i = 0; i < 5; i++) { + float fi = static_cast(i); + + auto xs = rerun::demo::linspace(-1.f, 1.f, 5); + auto zs = rerun::demo::linspace(fi / 10.f, fi, 5); + for (size_t j = 0; j < 5; j++) { + std::array origin = {xs[j], xs[j], 0.0}; + std::array vector = {xs[j], xs[j], zs[j]}; + + origins.emplace_back(origin); + vectors.emplace_back(vector); + } + } + + // At each timestep, all arrows share the same but changing color. + std::vector colors = {0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF}; + + // Log at seconds 10-14 + auto times = rerun::Collection{10s, 11s, 12s, 13s, 14s}; + auto time_column = rerun::TimeColumn::from_durations("time", std::move(times)); + + auto arrows = + rerun::Arrows3D().with_origins(origins).with_vectors(vectors).columns({5, 5, 5, 5, 5}); + + rec.send_columns( + "arrows", + time_column, + arrows, + rerun::Arrows3D::update_fields().with_colors(colors).columns() + ); +} diff --git a/docs/snippets/all/archetypes/arrows3d_column_updates.py b/docs/snippets/all/archetypes/arrows3d_column_updates.py new file mode 100644 index 000000000000..0441e5be08ed --- /dev/null +++ b/docs/snippets/all/archetypes/arrows3d_column_updates.py @@ -0,0 +1,28 @@ +""" +Update a set of vectors over time, in a single operation. + +This is semantically equivalent to the `arrows3d_row_updates` example, albeit much faster. +""" + +import numpy as np +import rerun as rr + +rr.init("rerun_example_arrows3d_column_updates", spawn=True) + +# Prepare a fixed sequence of arrows over 5 timesteps. +# Origins stay constant, vectors change magnitude and direction, and each timestep has a unique color. +times = np.arange(10, 15, 1.0) + +# At each time step, all arrows maintain their origin. +origins = [np.linspace((-1, -1, 0), (1, 1, 0), 5)] * 5 +vectors = [np.linspace((1, 1, i / 10), (1, 1, i), 5) for i in range(5)] + + +# At each timestep, all arrows share the same but changing color. +colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] + +rr.send_columns( + "arrows", + indexes=[rr.IndexColumn("time", timedelta=times)], + columns=[*rr.Arrows3D.columns(origins=origins, vectors=vectors, colors=colors)], +) diff --git a/docs/snippets/all/archetypes/arrows3d_column_updates.rs b/docs/snippets/all/archetypes/arrows3d_column_updates.rs new file mode 100644 index 000000000000..f43e2f35227b --- /dev/null +++ b/docs/snippets/all/archetypes/arrows3d_column_updates.rs @@ -0,0 +1,40 @@ +//! Update a set of vectors over time, in a single operation. +//! +//! This is semantically equivalent to the `arrows3d_row_updates` example, albeit much faster. + +use rerun::demo_util::linspace; + +fn main() -> Result<(), Box> { + let rec = + rerun::RecordingStreamBuilder::new("rerun_example_arrows3d_column_updates").spawn()?; + let times = rerun::TimeColumn::new_duration_seconds("time", 10..15); + + // Prepare a fixed sequence of arrows over 5 timesteps. + // Origins stay constant, vectors change magnitude and direction, and each timestep has a unique color. + let (origins, vectors): (Vec<_>, Vec<_>) = (0..5) + .map(|i| { + let i = i as f32; + ( + linspace(-1., 1., 5).map(move |x| (x, x, 0.)), + linspace(-1., 1., 5) + .zip(linspace(i / 10., i, 5)) + .map(|(x, z)| (x, x, z)), + ) + }) + .collect(); + + // At each timestep, all arrows share the same but changing color. + let colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF]; + + let arrows = rerun::Arrows3D::update_fields() + .with_origins(origins.into_iter().flatten()) + .with_vectors(vectors.into_iter().flatten()) + .columns([5, 5, 5, 5, 5])?; + let color = rerun::Arrows3D::update_fields() + .with_colors(colors) + .columns_of_unit_batches()?; + + rec.send_columns("arrows", [times], arrows.chain(color))?; + + Ok(()) +} diff --git a/docs/snippets/all/archetypes/arrows3d_row_updates.cpp b/docs/snippets/all/archetypes/arrows3d_row_updates.cpp new file mode 100644 index 000000000000..ffc6466eacf5 --- /dev/null +++ b/docs/snippets/all/archetypes/arrows3d_row_updates.cpp @@ -0,0 +1,49 @@ +// Update a set of vectors over time. +// +// See also the `arrows3d_column_updates` example, which achieves the same thing in a single operation. + +#include +#include + +#include +#include + +int main() { + const auto rec = rerun::RecordingStream("rerun_example_arrows3d_row_updates"); + rec.spawn().exit_on_failure(); + + // Prepare a fixed sequence of arrows over 5 timesteps. + // Origins stay constant, vectors change magnitude and direction, and each timestep has a unique color. + std::vector, 5>> origins; + std::vector, 5>> vectors; + + for (size_t i = 0; i < 5; i++) { + float fi = static_cast(i); + + auto xs = rerun::demo::linspace(-1.f, 1.f, 5); + auto zs = rerun::demo::linspace(fi / 10.f, fi, 5); + + std::array, 5> origin; + std::array, 5> vector; + for (size_t j = 0; j < 5; j++) { + origin[j] = {xs[j], xs[j], 0.0}; + vector[j] = {xs[j], xs[j], zs[j]}; + } + + origins.emplace_back(origin); + vectors.emplace_back(vector); + } + + // At each timestep, all arrows share the same but changing color. + std::vector colors = {0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF}; + + for (size_t i = 0; i < 5; i++) { + rec.set_index_duration_secs("time", 10.0 + static_cast(i)); + rec.log( + "arrows", + rerun::Arrows3D::from_vectors(vectors[i]) + .with_origins(origins[i]) + .with_colors(colors[i]) + ); + } +} diff --git a/docs/snippets/all/archetypes/arrows3d_row_updates.py b/docs/snippets/all/archetypes/arrows3d_row_updates.py new file mode 100644 index 000000000000..eb60b93076ad --- /dev/null +++ b/docs/snippets/all/archetypes/arrows3d_row_updates.py @@ -0,0 +1,26 @@ +""" +Update a set of vectors over time. + +See also the `arrows3d_column_updates` example, which achieves the same thing in a single operation. +""" + +import numpy as np +import rerun as rr + +rr.init("rerun_example_arrows3d_row_updates", spawn=True) + +# Prepare a fixed sequence of arrows over 5 timesteps. +# Origins stay constant, vectors change magnitude and direction, and each timestep has a unique color. +times = np.arange(10, 15, 1.0) + +# At each time step, all arrows maintain their origin. +origins = np.linspace((-1, -1, 0), (1, 1, 0), 5) +vectors = [np.linspace((1, 1, i / 10), (1, 1, i), 5) for i in range(5)] + + +# At each timestep, all arrows share the same but changing color. +colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF] + +for i in range(5): + rr.set_index("time", timedelta=10 + i) + rr.log("arrows", rr.Arrows3D(vectors=vectors[i], origins=origins, colors=colors[i])) diff --git a/docs/snippets/all/archetypes/arrows3d_row_updates.rs b/docs/snippets/all/archetypes/arrows3d_row_updates.rs new file mode 100644 index 000000000000..d99e21d89733 --- /dev/null +++ b/docs/snippets/all/archetypes/arrows3d_row_updates.rs @@ -0,0 +1,38 @@ +//! Update a set of vectors over time. +//! +//! See also the `arrows3d_column_updates` example, which achieves the same thing in a single operation. + +use rerun::demo_util::linspace; + +fn main() -> Result<(), Box> { + let rec = rerun::RecordingStreamBuilder::new("rerun_example_arrows3d_row_updates").spawn()?; + + // Prepare a fixed sequence of arrows over 5 timesteps. + // Origins stay constant, vectors change magnitude and direction, and each timestep has a unique color. + let (origins, vectors): (Vec<_>, Vec<_>) = (0..5) + .map(|i| { + let i = i as f32; + ( + linspace(-1., 1., 5).map(move |x| (x, x, 0.)), + linspace(-1., 1., 5) + .zip(linspace(i / 10., i, 5)) + .map(|(x, z)| (x, x, z)), + ) + }) + .collect(); + + // At each timestep, all arrows share the same but changing color. + let colors = [0xFF0000FF, 0x00FF00FF, 0x0000FFFF, 0xFFFF00FF, 0x00FFFFFF]; + + for (time, origins, vectors, color) in itertools::izip!(10..15, origins, vectors, colors) { + rec.set_duration_seconds("time", time); + + let arrows = rerun::Arrows3D::from_vectors(vectors) + .with_origins(origins) + .with_colors([color]); + + rec.log("arrows", &arrows)?; + } + + Ok(()) +} diff --git a/docs/snippets/snippets.toml b/docs/snippets/snippets.toml index 10315d74992b..4426fad1a937 100644 --- a/docs/snippets/snippets.toml +++ b/docs/snippets/snippets.toml @@ -20,6 +20,7 @@ features = [ [ "Update rows", [ + "archetypes/arrows3d_row_updates", "archetypes/scalar_row_updates", "archetypes/points3d_row_updates", "archetypes/transform3d_row_updates", @@ -28,6 +29,7 @@ features = [ [ "Update columns", [ + "archetypes/arrows3d_row_columns", "archetypes/scalar_column_updates", "archetypes/points3d_column_updates", "archetypes/transform3d_column_updates", diff --git a/lychee.toml b/lychee.toml index e8605a4a51e2..e1dc39bbd204 100644 --- a/lychee.toml +++ b/lychee.toml @@ -157,22 +157,10 @@ exclude = [ # '^file:///', # Ignore local file links. They need to be tested, but it's useful for external links we have to ping. # Snippets that haven't been released yet. - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_column_updates.rs', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.cpp', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.py', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates.rs', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.cpp', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.py', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/points3d_partial_updates_legacy.rs', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.cpp', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.py', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/transform3d_partial_updates.rs', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/howto/any_batch_value_column_updates.cpp', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/howto/any_batch_value_column_updates.rs', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/howto/any_values_column_updates.cpp', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/howto/any_values_column_updates.rs', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/any_values.cpp', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/any_values.rs', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.cpp', - 'https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/tutorials/extra_values.rs', + "https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.rs", + "https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_column_updates.rs", + "https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_column_updates.cpp", + "https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.cpp", + "https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_row_updates.py", + "https://github.com/rerun-io/rerun/blob/main/docs/snippets/all/archetypes/arrows3d_column_updates.py", ] diff --git a/rerun_py/rerun_sdk/rerun/_validators.py b/rerun_py/rerun_sdk/rerun/_validators.py index f6cb4c6da37b..15225f2f7990 100644 --- a/rerun_py/rerun_sdk/rerun/_validators.py +++ b/rerun_py/rerun_sdk/rerun/_validators.py @@ -81,10 +81,9 @@ def flat_np_array_from_array_like(array: npt.NDArray[Any], dimension: int) -> np if len(array.shape) == 1: valid = (array.shape[0] % dimension) == 0 elif len(array.shape) >= 2: - valid = array.shape[1] == dimension - - # Don't care about trailing dimensions if they're all 1. - valid = valid and all(d == 1 for d in array.shape[2:]) + # Get the last dimension that is not 1. If all dimensions are 1, this returns 1. + last_non_singleton = next((d for d in reversed(array.shape[1:]) if d != 1), 1) + valid = last_non_singleton == dimension if not valid: raise ValueError( diff --git a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py index 800617498a3b..cb9290c677da 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/annotation_context.py @@ -171,8 +171,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py index 7b90addbb5fc..5c48e9eb94ca 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows2d.py @@ -243,8 +243,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py index 85847de00234..bd4afbefd3d3 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/arrows3d.py @@ -229,8 +229,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py index 95de65c23a05..0af59dacb9aa 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset3d.py @@ -192,8 +192,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py index 053c22772e7b..8444455e1a26 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/asset_video.py @@ -226,8 +226,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py index 63400ac74eec..3405236b10ee 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/bar_chart.py @@ -167,8 +167,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py index b0d6c017a213..b0f56bb42284 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes2d.py @@ -228,8 +228,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py index 980857897295..0193c1e1bf32 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/boxes3d.py @@ -276,8 +276,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py index 6bf1da9f50b8..c86213d276df 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/capsules3d.py @@ -274,8 +274,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/clear.py b/rerun_py/rerun_sdk/rerun/archetypes/clear.py index b5297c9bfb3c..87c99d150a0d 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/clear.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/clear.py @@ -142,8 +142,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py index 43b254ef8b53..8c11df4fd813 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/depth_image.py @@ -270,8 +270,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py index df3e94d97e3b..cc352363e47a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/ellipsoids3d.py @@ -277,8 +277,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py index 82fb1c33d349..0e24d244587a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/encoded_image.py @@ -187,8 +187,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py index 90f5249629e4..882bf2f05c5b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_line_strings.py @@ -183,8 +183,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py index 501e559373dd..b07af7cede2e 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/geo_points.py @@ -186,8 +186,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py index ad01961f2479..d0919cd1ff2b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_edges.py @@ -183,8 +183,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py index 49c8e4bb7293..57cccec697e2 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/graph_nodes.py @@ -240,8 +240,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/image.py b/rerun_py/rerun_sdk/rerun/archetypes/image.py index b57ef3e7b754..59007f3689fd 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/image.py @@ -221,8 +221,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py index b3f4ab534f42..d3285b28ae52 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/instance_poses3d.py @@ -245,8 +245,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py index 534e3b8eeeca..ef53f7f93256 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips2d.py @@ -319,8 +319,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py index 2c7c5f69efd0..386cb74f2e61 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/line_strips3d.py @@ -309,8 +309,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py index 7d4bc22e4d6f..32ccf84f7ad7 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/mesh3d.py @@ -292,8 +292,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py index 12d289f7c652..8653accc738a 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/pinhole.py @@ -267,8 +267,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py index e94a3bfb50f4..e54deb6e6530 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points2d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points2d.py @@ -298,8 +298,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py index a9f7b43eb607..0bd1cb3a8b7b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/points3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/points3d.py @@ -344,8 +344,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py index 77b640b7b3b0..455196fe50b4 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/scalar.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/scalar.py @@ -196,8 +196,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py index 0f1574abf4a3..5794465a98a1 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/segmentation_image.py @@ -189,8 +189,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py index 69035631dee9..4636d62019e7 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_line.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_line.py @@ -265,8 +265,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py index 4faf97813a14..a67bac7909ac 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/series_point.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/series_point.py @@ -267,8 +267,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py index d059ebbac33a..6475c7278352 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/tensor.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/tensor.py @@ -175,8 +175,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py index 725fa8fe6039..250fe9b3a40b 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_document.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_document.py @@ -227,8 +227,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py index cc8e02a17689..56812a32e892 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/text_log.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/text_log.py @@ -196,8 +196,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py index 6e9ce2ec708e..08b5a902d64c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py @@ -443,8 +443,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] 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 5c996f2496a6..03a49c8447d7 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/video_frame_reference.py @@ -242,8 +242,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py index 2f102b0de940..0cbd91079c96 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/view_coordinates.py @@ -173,8 +173,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py index c6775d645927..3cb6f4abaaf4 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer1.py @@ -280,8 +280,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py index 057716e88557..6ecbfeb816c0 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer2.py @@ -256,8 +256,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py index b84b0fcaaebb..b86458a575f3 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer3.py @@ -249,8 +249,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py index 5323aab974a6..e798eba3fe40 100644 --- a/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py +++ b/rerun_py/tests/test_types/archetypes/affix_fuzzer4.py @@ -249,8 +249,8 @@ def columns( for batch in batches: arrow_array = batch.as_arrow_array() - # For primitive arrays, we infer partition size from the input shape. - if pa.types.is_primitive(arrow_array.type): + # For primitive arrays and fixed size list arrays, we infer partition size from the input shape. + if pa.types.is_primitive(arrow_array.type) or pa.types.is_fixed_size_list(arrow_array.type): param = kwargs[batch.component_descriptor().archetype_field_name] # type: ignore[index] shape = np.shape(param) # type: ignore[arg-type] diff --git a/rerun_py/tests/unit/test_validators.py b/rerun_py/tests/unit/test_validators.py new file mode 100644 index 000000000000..5c504a256766 --- /dev/null +++ b/rerun_py/tests/unit/test_validators.py @@ -0,0 +1,65 @@ +from __future__ import annotations + +from typing import Any + +import numpy as np +import numpy.typing as npt +import pytest +from rerun._validators import flat_np_array_from_array_like + +VALID_CASES = [ + # 1D array: length is a multiple of dimension + (np.array([1, 2, 3, 4, 5, 6]), 3), + (np.array([10, 20, 30, 40]), 2), + # 2D array: shape is (n, dimension) + (np.array([[1, 2, 3], [4, 5, 6]]), 3), + # 3D array with extra singleton dimensions: last non-singleton dimension is dimension + (np.array([[[1, 2, 3]], [[4, 5, 6]]]), 3), + # Edge case: multi-dimensional array where all non-first dimensions are singletons (defaults to 1) + (np.array([[[1]]]), 1), + # Array of shape (1, 1, 1, 3) + (np.array([[[[1, 2, 3]]]]), 3), + # Array of shape (1, 1, 2, 3) + (np.array([[[[1, 2, 3], [4, 5, 6]]]]), 3), + # Array of shape (2, 2, 3) + ( + np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]), + 3, + ), + # Array of shape (5, 1, 1, 3) + (np.arange(15).reshape(5, 1, 1, 3), 3), + # Array of shape (2, 1, 2) where the last non-singleton dimension is 2 + (np.array([[[1, 2]], [[3, 4]]]), 2), +] + + +@pytest.mark.parametrize(["input_array", "dimension"], VALID_CASES) +def test_flat_np_array_from_array_like_valid(input_array: npt.NDArray[Any], dimension: int) -> None: + np.testing.assert_array_equal(flat_np_array_from_array_like(input_array, dimension), input_array.reshape(-1)) + + +INVALID_CASES = [ + # 1D array: length not a multiple of dimension + (np.array([1, 2, 3, 4]), 3), + (np.array([1, 2, 3]), 2), + # 2D array: shape is (n, m) where m != dimension + (np.array([[1, 2], [3, 4]]), 3), + # 3D array: last non-singleton dimension is not equal to dimension + (np.array([[[1, 2]], [[3, 4]]]), 3), + # Edge case: multi-dimensional array where all non-first dimensions are singletons (defaults to 1) but dimension is not 1 + (np.array([[[1]]]), 2), + # 3D array with shape (2, 2, 2): last non-singleton dimension is 2, not equal to expected 3 + (np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]), 3), + # 2D array with shape (3, 4): last dimension is 4, expected 3 + (np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]), 3), + # 3D array with shape (1, 1, 4): last non-singleton dimension is 4, expected 3 + (np.array([[[1, 2, 3, 4]]]), 3), + # 4D array with shape (1, 2, 1, 3): last non-singleton dimension is 3, expected 2 + (np.array([[[[1, 2, 3]], [[4, 5, 6]]]]), 2), +] + + +@pytest.mark.parametrize(["input_array", "dimension"], INVALID_CASES) +def test_flat_np_array_from_array_like_invalid(input_array: npt.NDArray[Any], dimension: int) -> None: + with pytest.raises(ValueError): + flat_np_array_from_array_like(input_array, dimension)