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

Allow showing image shaped tensors in the tensor view #3583

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 14 additions & 40 deletions crates/re_space_view_tensor/src/view_part_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use re_types::{
Archetype, ComponentNameSet,
};
use re_viewer_context::{
default_heuristic_filter, NamedViewSystem, SpaceViewSystemExecutionError, TensorDecodeCache,
ViewContextCollection, ViewPartSystem, ViewQuery, ViewerContext,
NamedViewSystem, SpaceViewSystemExecutionError, TensorDecodeCache, ViewContextCollection,
ViewPartSystem, ViewQuery, ViewerContext,
};

#[derive(Default)]
Expand All @@ -35,28 +35,6 @@ impl ViewPartSystem for TensorSystem {
std::iter::once(Tensor::indicator().name()).collect()
}

/// Tensor view doesn't handle 2D images, see [`TensorSystem::load_tensor_entity`]
fn heuristic_filter(
&self,
store: &re_arrow_store::DataStore,
ent_path: &EntityPath,
query: &LatestAtQuery,
entity_components: &ComponentNameSet,
) -> bool {
if !default_heuristic_filter(entity_components, &self.indicator_components()) {
return false;
}

// NOTE: We want to make sure we query at the right time, otherwise we might take into
// account a `Clear()` that actually only applies into the future, and then
// `is_shaped_like_an_image` will righfully fail because of the empty tensor.
if let Some(tensor) = store.query_latest_component::<TensorData>(ent_path, query) {
!tensor.is_shaped_like_an_image() && !tensor.is_vector()
} else {
false
}
}

fn execute(
&mut self,
ctx: &mut ViewerContext<'_>,
Expand Down Expand Up @@ -93,22 +71,18 @@ impl TensorSystem {
_props: &EntityProperties,
tensor: TensorData,
) {
if !tensor.is_shaped_like_an_image() {
// NOTE: Tensors don't support batches at the moment so always splat.
let tensor_path_hash = InstancePathHash::entity_splat(ent_path).versioned(row_id);
match ctx
.cache
.entry(|c: &mut TensorDecodeCache| c.entry(tensor_path_hash, tensor.0))
{
Ok(tensor) => {
let instance_path = InstancePath::instance(ent_path.clone(), InstanceKey(0));
self.tensors.insert(instance_path, (row_id, tensor));
}
Err(err) => {
re_log::warn_once!(
"Failed to decode decoding tensor at path {ent_path}: {err}"
);
}
// NOTE: Tensors don't support batches at the moment so always splat.
let tensor_path_hash = InstancePathHash::entity_splat(ent_path).versioned(row_id);
match ctx
.cache
.entry(|c: &mut TensorDecodeCache| c.entry(tensor_path_hash, tensor.0))
{
Ok(tensor) => {
let instance_path = InstancePath::instance(ent_path.clone(), InstanceKey(0));
self.tensors.insert(instance_path, (row_id, tensor));
}
Err(err) => {
re_log::warn_once!("Failed to decode decoding tensor at path {ent_path}: {err}");
}
}
}
Expand Down
24 changes: 10 additions & 14 deletions crates/re_viewport/src/space_view_heuristics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use nohash_hasher::{IntMap, IntSet};

use re_arrow_store::{LatestAtQuery, Timeline};
use re_data_store::EntityPath;
use re_types::archetypes::Image;
use re_types::components::{DisconnectedSpace, TensorData};
use re_types::ComponentNameSet;
use re_types::{Archetype, ComponentNameSet};
use re_viewer_context::{
AutoSpawnHeuristic, SpaceViewClassName, ViewContextCollection, ViewPartCollection,
ViewSystemName, ViewerContext,
Expand Down Expand Up @@ -123,22 +124,17 @@ pub fn all_possible_space_views(
.collect_vec()
}

fn contains_any_image(
entity_path: &EntityPath,
store: &re_arrow_store::DataStore,
query: &LatestAtQuery,
) -> bool {
if let Some(tensor) = store.query_latest_component::<TensorData>(entity_path, query) {
tensor.is_shaped_like_an_image()
} else {
false
}
fn contains_any_image(ent_path: &EntityPath, store: &re_arrow_store::DataStore) -> bool {
store
.all_components(&Timeline::log_time(), ent_path)
.unwrap_or_default()
.iter()
.any(|comp| *comp == Image::indicator().name())
}

fn is_interesting_space_view_at_root(
data_store: &re_arrow_store::DataStore,
candidate: &SpaceViewBlueprint,
query: &LatestAtQuery,
) -> bool {
// Not interesting if it has only data blueprint groups and no direct entities.
// -> If there In that case we want spaceviews at those groups.
Expand All @@ -149,7 +145,7 @@ fn is_interesting_space_view_at_root(
// If there are any images directly under the root, don't create root space either.
// -> For images we want more fine grained control and resort to child-of-root spaces only.
for entity_path in &candidate.contents.root_group().entities {
if contains_any_image(entity_path, data_store, query) {
if contains_any_image(entity_path, data_store) {
return false;
}
}
Expand Down Expand Up @@ -208,7 +204,7 @@ pub fn default_created_space_views(
.iter()
.filter_map(|space_view_candidate| {
(space_view_candidate.space_origin.is_root()
&& is_interesting_space_view_at_root(store, space_view_candidate, &query))
&& is_interesting_space_view_at_root(store, space_view_candidate))
.then_some(*space_view_candidate.class_name())
})
.collect::<Vec<_>>();
Expand Down