Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5096,6 +5096,18 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"

[[package]]
name = "japanese_alley"
version = "0.26.0-alpha.1+dev"
dependencies = [
"anyhow",
"arrow",
"clap",
"itertools 0.14.0",
"re_arrow_util",
"rerun",
]

[[package]]
name = "jiff"
version = "0.2.15"
Expand Down
2 changes: 1 addition & 1 deletion crates/utils/re_arrow_util/src/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ impl Transform for Flatten {
///
/// The underlying bytes buffer is reused, making this transformation almost zero-copy.
#[derive(Clone, Debug, Default)]
pub struct BinaryToListUInt8<O1: OffsetSizeTrait, O2: OffsetSizeTrait = O1> {
pub struct BinaryToListUInt8<O1: OffsetSizeTrait = i32, O2: OffsetSizeTrait = O1> {
_from_offset: PhantomData<O1>,
_to_offset: PhantomData<O2>,
}
Expand Down
19 changes: 19 additions & 0 deletions examples/rust/japanese_alley/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "japanese_alley"
version = "0.26.0-alpha.1+dev"
edition = "2024"
rust-version = "1.88"
license = "MIT OR Apache-2.0"
publish = false

[dependencies]
rerun = { path = "../../../crates/top/rerun", features = [
"web_viewer",
"clap",
] }

anyhow.workspace = true
arrow.workspace = true
clap = { workspace = true, features = ["derive"] }
itertools.workspace = true
re_arrow_util = { workspace = true }
109 changes: 109 additions & 0 deletions examples/rust/japanese_alley/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use arrow::array::{Float32Array, Float64Array, ListArray};
use re_arrow_util::transform::{
BinaryToListUInt8, Cast, MapFixedSizeList, MapList, StructToFixedList, Transform,
};
use rerun::{
EncodedImage, InstancePoses3D, Points3D,
dataframe::EntityPathFilter,
external::re_log,
lenses::{Error, LensBuilder, LensesSink, Op},
sink::GrpcSink,
};

#[derive(Debug, clap::Parser)]
#[clap(author, version, about)]
struct Args {
#[command(flatten)]
rerun: rerun::clap::RerunArgs,

/// The path to the MCAP file.
filepath: std::path::PathBuf,
}

fn list_binary_to_list_uint8(input: &ListArray) -> Result<ListArray, Error> {
Ok(MapList::new(BinaryToListUInt8::<i32>::new()).transform(input)?)
}

fn convert_list_struct_to_list_fixed(list_array: &ListArray) -> Result<ListArray, Error> {
// Arrow transformations can work on any Arrow-level.
let pipeline = MapList::new(StructToFixedList::new(["x", "y", "z"]).then(
MapFixedSizeList::new(Cast::<Float64Array, Float32Array>::new()),
));
Ok(pipeline.transform(list_array)?)
}

// TODO: This example is still missing `tf`-style transforms.

fn main() -> anyhow::Result<()> {
re_log::setup_logging();

use clap::Parser as _;
let args = Args::parse();

// The following could be improved with columnar archetype APIs.
let dummy_point = Points3D::new([[0.0f32, 0.0, 0.0]])
.columns_of_unit_batches()
.unwrap()
.next()
.unwrap();

// plural
let instance_poses_lens =
LensBuilder::for_input_column(EntityPathFilter::all(), "foxglove.PosesInFrame:message")
.add_component_column(
InstancePoses3D::descriptor_translations(),
[
// Lens operations always work on component-column level.
Op::access_field("poses"),
Op::flatten(),
Op::access_field("position"),
Op::func(convert_list_struct_to_list_fixed),
],
)
.add_static_component_column(
dummy_point.descriptor.clone(),
[Op::constant(dummy_point.list_array.clone())],
)
.build();

// singular
let instance_pose_lens =
LensBuilder::for_input_column(EntityPathFilter::all(), "foxglove.PoseInFrame:message")
.add_component_column(
InstancePoses3D::descriptor_translations(),
[
// Lens operations always work on component-column level.
Op::access_field("pose"),
Op::access_field("position"),
Op::func(convert_list_struct_to_list_fixed),
],
)
.add_static_component_column(
dummy_point.descriptor,
[Op::constant(dummy_point.list_array)],
)
.build();

let image_lens =
LensBuilder::for_input_column(EntityPathFilter::all(), "foxglove.CompressedImage:message")
// TODO: We leave out the `format` column because the `png` contents are not a valid MIME type.
.add_component_column(
EncodedImage::descriptor_blob(),
[
Op::access_field("data"),
Op::func(list_binary_to_list_uint8),
],
)
.build();

let lenses_sink = LensesSink::new(GrpcSink::default())
.with_lens(image_lens)
.with_lens(instance_pose_lens)
.with_lens(instance_poses_lens);

let (rec, _serve_guard) = args.rerun.init("rerun_example_japanese_alley")?;
rec.set_sink(Box::new(lenses_sink));
rec.log_file_from_path(args.filepath, None, false)?;

Ok(())
}
Loading