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

Fix recommendation from one Space View class affecting recommendation from another #5554

Merged
merged 4 commits into from
Mar 18, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/re_types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ itertools.workspace = true
linked-hash-map.workspace = true
mime_guess2.workspace = true
ndarray.workspace = true
nohash-hasher.workspace = true
once_cell.workspace = true
ply-rs.workspace = true
smallvec.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/re_types/src/blueprint/components/mod.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use super::ViewerRecommendationHash;

impl std::hash::Hash for ViewerRecommendationHash {
#[inline]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
state.write_u64(self.0 .0);
}
}

impl nohash_hasher::IsEnabled for ViewerRecommendationHash {}
24 changes: 22 additions & 2 deletions crates/re_viewer_context/src/space_view/spawn_heuristics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use re_log_types::{EntityPath, EntityPathFilter, EntityPathSubs};
use re_log_types::{hash::Hash64, EntityPath, EntityPathFilter, EntityPathSubs};

use crate::SpaceViewClassIdentifier;

/// Properties of a space view that as recommended to be spawned by default via space view spawn heuristics.
#[derive(Hash, Debug, Clone)]
#[derive(Debug, Clone)]
pub struct RecommendedSpaceView {
pub origin: EntityPath,
pub query_filter: EntityPathFilter,
Expand Down Expand Up @@ -42,4 +44,22 @@ impl RecommendedSpaceView {
pub fn root() -> Self {
Self::new_subtree(EntityPath::root())
}

/// Hash together with the Space View class id to the `ViewerRecommendationHash` component.
///
/// Recommendations are usually tied to a specific Space View class.
/// Therefore, to identify a recommendation for identification purposes, the class id should be included in the hash.
pub fn recommendation_hash(
&self,
class_id: SpaceViewClassIdentifier,
) -> re_types::blueprint::components::ViewerRecommendationHash {
let Self {
origin,
query_filter,
} = self;

Hash64::hash((origin, query_filter, class_id))
.hash64()
.into()
}
}
23 changes: 12 additions & 11 deletions crates/re_viewport/src/viewport_blueprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use smallvec::SmallVec;

use re_data_store::LatestAtQuery;
use re_entity_db::EntityPath;
use re_log_types::hash::Hash64;
use re_query::query_archetype;
use re_space_view::SpaceViewBlueprint;
use re_types::blueprint::components::ViewerRecommendationHash;
Expand Down Expand Up @@ -59,7 +58,7 @@ pub struct ViewportBlueprint {
auto_space_views: AtomicBool,

/// Hashes of all recommended space views the viewer has already added and that should not be added again.
past_viewer_recommendation_hashes: IntSet<Hash64>,
past_viewer_recommendations: IntSet<ViewerRecommendationHash>,

/// Channel to pass Blueprint mutation messages back to the [`crate::Viewport`]
tree_action_sender: std::sync::mpsc::Sender<TreeAction>,
Expand All @@ -80,7 +79,7 @@ impl ViewportBlueprint {
maximized,
auto_layout,
auto_space_views,
past_viewer_recommendations: past_viewer_recommendation_hashes,
past_viewer_recommendations,
} = match query_archetype(blueprint_db.store(), query, &VIEWPORT_PATH.into())
.and_then(|arch| arch.to_archetype())
{
Expand Down Expand Up @@ -149,10 +148,9 @@ impl ViewportBlueprint {
root_container,
);

let past_viewer_recommendation_hashes = past_viewer_recommendation_hashes
let past_viewer_recommendations = past_viewer_recommendations
.unwrap_or_default()
.into_iter()
.map(|h| Hash64::from_u64(h.0 .0))
.collect();

ViewportBlueprint {
Expand All @@ -163,7 +161,7 @@ impl ViewportBlueprint {
maximized: maximized.map(|id| id.0.into()),
auto_layout,
auto_space_views,
past_viewer_recommendation_hashes,
past_viewer_recommendations,
tree_action_sender,
}
}
Expand Down Expand Up @@ -301,8 +299,8 @@ impl ViewportBlueprint {
// Remove all space views that we already spawned via heuristic before.
recommended_space_views.retain(|recommended_view| {
!self
.past_viewer_recommendation_hashes
.contains(&Hash64::hash(recommended_view))
.past_viewer_recommendations
.contains(&recommended_view.recommendation_hash(class_id))
});

// Each of the remaining recommendations would individually be a candidate for spawning if there were
Expand All @@ -321,11 +319,14 @@ impl ViewportBlueprint {
// mean we should suddenly add `/camera/**` to the viewport.
if !recommended_space_views.is_empty() {
let new_viewer_recommendation_hashes = self
.past_viewer_recommendation_hashes
.past_viewer_recommendations
.iter()
.cloned()
.chain(recommended_space_views.iter().map(Hash64::hash))
.map(|hash| ViewerRecommendationHash(hash.hash64().into()))
.chain(
recommended_space_views
.iter()
.map(|recommendation| recommendation.recommendation_hash(class_id)),
)
.collect::<Vec<_>>();

ctx.save_blueprint_component(
Expand Down
2 changes: 0 additions & 2 deletions tests/python/release_checklist/check_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ def log_annotations() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
2 changes: 0 additions & 2 deletions tests/python/release_checklist/check_container_hierarchy.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
2 changes: 0 additions & 2 deletions tests/python/release_checklist/check_focus.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ def log_some_space_views() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
2 changes: 0 additions & 2 deletions tests/python/release_checklist/check_heuristics_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ def log_images() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
Reset the blueprint to make sure you are viewing new heuristics and not a cached blueprint.

### Action
You should see 4 space-views:
You should see 5 space-views:
- 2D: `image1` with an all red image
- 2D: `image2` with an all green image
- 2D: `3D/camera` with an all blue image
- 3D: `3D` with:
- a 3D box
- a pinhole camera, showing the blue image
- no red or green image
- Text: This readme.
"""


Expand All @@ -49,8 +50,6 @@ def log_3d_scene() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
39 changes: 39 additions & 0 deletions tests/python/release_checklist/check_heuristics_mixed_all_root.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from __future__ import annotations

import os
from argparse import Namespace
from uuid import uuid4

import rerun as rr

README = """
# Mixed objects Heuristics with everything directly under root

This checks whether the heuristics do the right thing with mixed 2D, 3D and test data.

### Action
You should see 4 space-views:
- 2D: Boxes and points, `$origin` == `/`
- 3D: 3D boxes, `$origin` == `/`
- Text log: A single log line, `$origin` == `/`
- Text: This readme, `$origin` == `/readme`
"""


def run(args: Namespace) -> None:
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

rr.log("boxes3d", rr.Boxes3D(centers=[[0, 0, 0], [1, 1.5, 1.15], [3, 2, 1]], half_sizes=[0.5, 1, 0.5] * 3))
rr.log("boxes2d", rr.Boxes2D(centers=[[0, 0], [1.3, 0.5], [3, 2]], half_sizes=[0.5, 1] * 3))
rr.log("text_logs", rr.TextLog("Hello, world!", level=rr.TextLogLevel.INFO))
rr.log("points2d", rr.Points2D([[0, 0], [1, 1], [3, 2]], labels=["a", "b", "c"]))
rr.log("readme", rr.TextDocument(README, media_type=rr.MediaType.MARKDOWN), timeless=True)


if __name__ == "__main__":
import argparse

parser = argparse.ArgumentParser(description="Interactive release checklist")
rr.script_add_args(parser)
args = parser.parse_args()
run(args)
2 changes: 0 additions & 2 deletions tests/python/release_checklist/check_hover_select_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ def log_points_2d() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,6 @@ def log_spatial() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
2 changes: 0 additions & 2 deletions tests/python/release_checklist/check_plot_overrides.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ def log_plots() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
2 changes: 0 additions & 2 deletions tests/python/release_checklist/check_scalar_clears.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ def log_plots() -> None:


def run(args: Namespace) -> None:
# TODO(cmc): I have no idea why this works without specifying a `recording_id`, but
# I'm not gonna rely on it anyway.
rr.script_setup(args, f"{os.path.basename(__file__)}", recording_id=uuid4())

log_readme()
Expand Down
Loading