Skip to content

Commit c88946f

Browse files
authored
Tensor view improvements (#9831)
1 parent 59e470a commit c88946f

File tree

2 files changed

+39
-26
lines changed

2 files changed

+39
-26
lines changed

crates/viewer/re_view_tensor/src/view_class.rs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use re_types::{
1616
use re_ui::{list_item, Help, UiExt as _};
1717
use re_view::{suggest_view_for_each_entity, view_property_ui};
1818
use re_viewer_context::{
19-
gpu_bridge, ColormapWithRange, IdentifiedViewSystem as _, IndicatedEntities,
19+
gpu_bridge, ColormapWithRange, IdentifiedViewSystem as _, IndicatedEntities, Item,
2020
MaybeVisualizableEntities, PerVisualizer, TensorStatsCache, TypedComponentFallbackProvider,
2121
ViewClass, ViewClassRegistryError, ViewId, ViewQuery, ViewState, ViewStateExt as _,
2222
ViewSystemExecutionError, ViewerContext, VisualizableEntities,
@@ -216,23 +216,38 @@ Set the displayed dimensions in a selection panel.",
216216

217217
let tensors = &system_output.view_systems.get::<TensorSystem>()?.tensors;
218218

219-
if tensors.len() > 1 {
220-
egui::Frame {
221-
inner_margin: re_ui::DesignTokens::view_padding().into(),
222-
..egui::Frame::default()
223-
}
224-
.show(ui, |ui| {
225-
ui.error_label(format!(
226-
"Can only show one tensor at a time; was given {}. Update the query so that it \
219+
let response = {
220+
let mut ui = ui.new_child(egui::UiBuilder::new().sense(egui::Sense::click()));
221+
222+
if tensors.len() > 1 {
223+
egui::Frame {
224+
inner_margin: re_ui::DesignTokens::view_padding().into(),
225+
..egui::Frame::default()
226+
}
227+
.show(&mut ui, |ui| {
228+
ui.error_label(format!(
229+
"Can only show one tensor at a time; was given {}. Update the query so that it \
227230
returns a single tensor entity and create additional views for the others.",
228-
tensors.len()
229-
));
230-
});
231-
} else if let Some(tensor_view) = tensors.first() {
232-
state.tensor = Some(tensor_view.clone());
233-
self.view_tensor(ctx, ui, state, query.view_id, &tensor_view.tensor)?;
234-
} else {
235-
ui.centered_and_justified(|ui| ui.label("(empty)"));
231+
tensors.len()
232+
));
233+
});
234+
} else if let Some(tensor_view) = tensors.first() {
235+
state.tensor = Some(tensor_view.clone());
236+
self.view_tensor(ctx, &mut ui, state, query.view_id, &tensor_view.tensor)?;
237+
} else {
238+
ui.centered_and_justified(|ui| ui.label("(empty)"));
239+
}
240+
241+
ui.response()
242+
};
243+
244+
if response.hovered() {
245+
ctx.selection_state().set_hovered(Item::View(query.view_id));
246+
}
247+
248+
if response.clicked() {
249+
ctx.selection_state()
250+
.set_selection(Item::View(query.view_id));
236251
}
237252

238253
Ok(())
@@ -297,7 +312,7 @@ impl TensorView {
297312
}),
298313
];
299314

300-
egui::ScrollArea::both().show(ui, |ui| {
315+
egui::ScrollArea::both().auto_shrink(false).show(ui, |ui| {
301316
if let Err(err) =
302317
self.tensor_slice_ui(ctx, ui, state, view_id, dimension_labels, &slice_selection)
303318
{
@@ -317,12 +332,12 @@ impl TensorView {
317332
dimension_labels: [Option<(String, bool)>; 2],
318333
slice_selection: &TensorSliceSelection,
319334
) -> anyhow::Result<()> {
320-
let (response, painter, image_rect) =
335+
let (response, image_rect) =
321336
self.paint_tensor_slice(ctx, ui, state, view_id, slice_selection)?;
322337

323338
if !response.hovered() {
324339
let font_id = egui::TextStyle::Body.resolve(ui.style());
325-
paint_axis_names(ui, &painter, image_rect, font_id, dimension_labels);
340+
paint_axis_names(ui, image_rect, font_id, dimension_labels);
326341
}
327342

328343
Ok(())
@@ -335,7 +350,7 @@ impl TensorView {
335350
state: &ViewTensorState,
336351
view_id: ViewId,
337352
slice_selection: &TensorSliceSelection,
338-
) -> anyhow::Result<(egui::Response, egui::Painter, egui::Rect)> {
353+
) -> anyhow::Result<(egui::Response, egui::Rect)> {
339354
re_tracing::profile_function!();
340355

341356
let Some(tensor_view) = state.tensor.as_ref() else {
@@ -411,7 +426,7 @@ impl TensorView {
411426
re_renderer::DebugLabel::from("tensor_slice"),
412427
)?;
413428

414-
Ok((response, painter, image_rect))
429+
Ok((response, image_rect))
415430
}
416431
}
417432

@@ -484,11 +499,12 @@ fn dimension_name(shape: &[TensorDimension], dim_idx: u32) -> String {
484499

485500
fn paint_axis_names(
486501
ui: &egui::Ui,
487-
painter: &egui::Painter,
488502
rect: egui::Rect,
489503
font_id: egui::FontId,
490504
dimension_labels: [Option<(String, bool)>; 2],
491505
) {
506+
let painter = ui.painter();
507+
492508
let [width, height] = dimension_labels;
493509
let (width_name, invert_width) =
494510
width.map_or((None, false), |(label, invert)| (Some(label), invert));

tests/python/release_checklist/check_1d_tensor_data.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121
* an image view with a 1D image
2222
* a bar chart
2323
24-
Known bugs:
25-
* TODO(#6695): When hovering over a the tensor view, a thin, black, rounded cutout appears.
26-
2724
Bonus actions:
2825
* use the ui to create a tensor/bar-chart with each of the entities no matter how it was logged
2926
* TODO(#5847): Right now tensors & bar charts can not be reinterpreted as 2D images.

0 commit comments

Comments
 (0)