Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Order-agnostic rrd compare command + snippet clean up #8843

Merged
merged 12 commits into from
Jan 29, 2025
53 changes: 42 additions & 11 deletions crates/top/rerun/src/commands/rrd/compare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,24 @@ use std::{
use anyhow::Context as _;
use itertools::{izip, Itertools};

use re_chunk::Chunk;

// ---

#[derive(Debug, Clone, clap::Parser)]
pub struct CompareCommand {
path_to_rrd1: String,
path_to_rrd2: String,

/// If specified, the comparison will focus purely on semantics, ignoring order.
///
/// The Rerun data model is itself unordered, and because many of the internal pipelines are
/// asynchronous by nature, it is very easy to end up with semantically identical, but
/// differently ordered data.
/// In most cases, the distinction is irrelevant, and you'd rather the comparison succeeds.
#[clap(long, default_value_t = false)]
unordered: bool,

/// If specified, dumps both .rrd files as tables.
#[clap(long, default_value_t = false)]
full_dump: bool,
Expand All @@ -27,6 +38,7 @@ impl CompareCommand {
let Self {
path_to_rrd1,
path_to_rrd2,
unordered,
full_dump,
} = self;

Expand Down Expand Up @@ -64,17 +76,36 @@ impl CompareCommand {
re_format::format_uint(chunks2.len()),
);

for (chunk1, chunk2) in izip!(chunks1, chunks2) {
anyhow::ensure!(
re_chunk::Chunk::are_similar(&chunk1, &chunk2),
"Chunks do not match:\n{}",
similar_asserts::SimpleDiff::from_str(
&format!("{chunk1}"),
&format!("{chunk2}"),
"got",
"expected",
),
);
let mut unordered_failed = false;
if *unordered {
let mut chunks2_opt: Vec<Option<Arc<Chunk>>> =
chunks2.clone().into_iter().map(Some).collect_vec();
'outer: for chunk1 in &chunks1 {
for chunk2 in chunks2_opt.iter_mut().filter(|c| c.is_some()) {
#[allow(clippy::unwrap_used)]
if re_chunk::Chunk::are_similar(chunk1, chunk2.as_ref().unwrap()) {
*chunk2 = None;
continue 'outer;
}
}
unordered_failed = true;
break;
}
}

if !*unordered || unordered_failed {
for (chunk1, chunk2) in izip!(chunks1, chunks2) {
anyhow::ensure!(
re_chunk::Chunk::are_similar(&chunk1, &chunk2),
"Chunks do not match:\n{}",
similar_asserts::SimpleDiff::from_str(
&format!("{chunk1}"),
&format!("{chunk2}"),
"got",
"expected",
),
);
}
}

re_log::debug!("{path_to_rrd1:?} and {path_to_rrd2:?} are similar enough.");
Expand Down
2 changes: 1 addition & 1 deletion docs/snippets/all/archetypes/image_send_columns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ int main() {
rerun::ColorModel::RGB,
rerun::ChannelDatatype::U8
);
rec.log_static("images", rerun::borrow(&format), rerun::Image::IndicatorComponent());
rec.log_static("images", rerun::Image::update_fields().with_format(format));

// Split up the image data into several components referencing the underlying data.
const size_t image_size_in_bytes = width * height * 3;
Expand Down
4 changes: 2 additions & 2 deletions docs/snippets/all/archetypes/image_send_columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
images[t, 50:150, (t * 10) : (t * 10 + 100), 1] = 255

# Log the ImageFormat and indicator once, as static.
format_static = rr.components.ImageFormat(width=width, height=height, color_model="RGB", channel_datatype="U8")
rr.send_columns("images", indexes=[], columns=rr.Image.columns(format=format_static))
format = rr.components.ImageFormat(width=width, height=height, color_model="RGB", channel_datatype="U8")
rr.log("images", rr.Image.from_fields(format=format), static=True)

# Send all images at once.
rr.send_columns(
Expand Down
10 changes: 2 additions & 8 deletions docs/snippets/all/archetypes/image_send_columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.fill(255);
}

// Send the ImageFormat and indicator once, as static.
// Log the ImageFormat and indicator once, as static.
let format = rerun::components::ImageFormat::rgb8([width as _, height as _]);
rec.send_columns(
"images",
[],
rerun::Image::update_fields()
.with_format(format)
.columns_of_unit_batches()?,
)?;
rec.log_static("images", &rerun::Image::update_fields().with_format(format))?;

// Split up the image data into several components referencing the underlying data.
let image_size_in_bytes = width * height * 3;
Expand Down
5 changes: 4 additions & 1 deletion docs/snippets/all/archetypes/mesh3d_partial_updates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ int main() {
mul_pos(factor, vertex_positions[1]),
mul_pos(factor, vertex_positions[2]),
};
rec.log("triangle", modified_vertex_positions);
rec.log(
"triangle",
rerun::Mesh3D::update_fields().with_vertex_positions(modified_vertex_positions)
);
}
}
40 changes: 5 additions & 35 deletions docs/snippets/snippets.toml
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,8 @@ quick_start = [ # These examples don't have exactly the same implementation.
"py",
"rust",
]
"archetypes/arrows3d_simple" = [ # TODO(#3206): examples use different RNGs
"cpp",
"archetypes/arrows3d_simple" = [ # Python uses doubles
"py",
"rust",
]
"archetypes/asset3d_out_of_tree" = [ # float issues since calculation is done slightly differently (also, Python uses doubles)
"cpp",
"py",
"rust",
]
"archetypes/bar_chart" = [ # On Windows this logs f64 instead of u64 unless a numpy array with explicit type is used.
"py",
Expand All @@ -221,11 +214,9 @@ quick_start = [ # These examples don't have exactly the same implementation.
"py",
"rust",
]
"archetypes/mesh3d_partial_updates" = [ # TODO(andreas): use new partial update api
"cpp",
"archetypes/mesh3d_partial_updates" = [ # Python uses doubles
"py",
"rust",
] # float precision issues
]
"archetypes/pinhole_simple" = [ # TODO(#3206): examples use different RNGs
"cpp",
"py",
Expand All @@ -249,17 +240,7 @@ quick_start = [ # These examples don't have exactly the same implementation.
"py",
"rust",
]
"archetypes/series_point_style" = [ # TODO(#5116): trigonometric functions have slightly different outcomes
"cpp",
"py",
"rust",
]
"archetypes/series_line_style" = [ # TODO(#5116):trigonometric functions have slightly different outcomes
"cpp",
"py",
"rust",
]
"archetypes/text_log_integration" = [ # The entity path will differ because the Rust code is part of a library
"archetypes/text_log_integration" = [ # The entity path will differ because the integrations work differently
"cpp",
"py",
"rust",
Expand All @@ -277,19 +258,8 @@ quick_start = [ # These examples don't have exactly the same implementation.
"py",
"rust",
]
"archetypes/image_send_columns" = [ # This mixes `log` and `send_columns`. Since `log` is suspect to delays by the batcher, this test gets flaky.
"cpp",
"rust",
]
"archetypes/mesh3d_instancing" = [ # TODO(#3235): Slight floating point differences in deg to rad conversion.
"cpp",
"py",
"rust",
]
"archetypes/video_auto_frames" = [ # This mixes `log` and `send_columns`. Since `log` is suspect to delays by the batcher, this test gets flaky.
"cpp",
"archetypes/mesh3d_instancing" = [ # Python uses doubles
"py",
"rust",
]

# `$config_dir` will be replaced with the absolute path of `docs/snippets`.
Expand Down
2 changes: 1 addition & 1 deletion scripts/roundtrip_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def roundtrip_env(*, save_path: str | None = None) -> dict[str, str]:


def run_comparison(rrd0_path: str, rrd1_path: str, full_dump: bool) -> None:
cmd = ["rerun", "rrd", "compare"]
cmd = ["rerun", "rrd", "compare", "--unordered"]
if full_dump:
cmd += ["--full-dump"]
cmd += [rrd0_path, rrd1_path]
Expand Down
Loading