Skip to content

Commit

Permalink
Dataframe view update and blueprint API (part 4): blueprint API (#7551)
Browse files Browse the repository at this point in the history
### What

This PR implements the blueprint API for the dataframe view:

```python
blueprint = rrb.Blueprint(
    rrb.DataframeView(
        origin="/trig",
        query=rrb.archetypes.DataframeQueryV2(
            timeline="t",
            filter_by_range=(rr.TimeInt(seconds=0), rr.TimeInt(seconds=20)),
            filter_by_event="/trig/tan_sparse:Scalar",
            select=["t", "log_tick", "/trig/sin:Scalar", "/trig/cos:Scalar", "/trig/tan_sparse:Scalar"],
        ),
    ),
)
```

The blueprint API is now functional and can be used to configure
everything in the new UI, which is _still_ mostly inoperative (except
for column visibility—this can be tested end-to-end).

<hr>

Part of a series to address #6896 and #7498.

All PRs:
- #7515
- #7516
- #7527 
- #7545
- #7551
- #7572
- #7573

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/7551?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/7551?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!
* [x] If have noted any breaking changes to the log API in
`CHANGELOG.md` and the migration guide

- [PR Build Summary](https://build.rerun.io/pr/7551)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
  • Loading branch information
abey79 authored Oct 3, 2024
1 parent fa6f0e8 commit c738b89
Show file tree
Hide file tree
Showing 15 changed files with 580 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace rerun.blueprint.datatypes;
//TODO(ab, jleibs): this probably needs reunification with whatever structure the data out API uses.
// Has to be a table because flatbuffer doesn't support strings in structs.
table ComponentColumnSelector (
"attr.python.aliases": "str",
"attr.rust.derive": "Default, PartialEq, Eq, Hash",
"attr.rerun.scope": "blueprint"
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ namespace rerun.blueprint.datatypes;
/// Configuration for the filter by event feature of the dataframe view.
// Has to be a table because flatbuffer doesn't support strings in structs.
table FilterByEvent (
"attr.rust.derive": "Default, PartialEq, Eq",
"attr.rerun.scope": "blueprint"
"attr.python.aliases": "blueprint_datatypes.ComponentColumnSelectorLike",
"attr.rust.derive": "Default, PartialEq, Eq",
"attr.rerun.scope": "blueprint"
) {
/// Whether the filter by event feature is active.
active: rerun.datatypes.Bool (order: 100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace rerun.blueprint.datatypes;
/// List of selected columns in a dataframe.
// Has to be a table because flatbuffer doesn't support strings in structs.
table SelectedColumns (
"attr.python.aliases": "Sequence[Union[blueprint_datatypes.ComponentColumnSelectorLike, datatypes.Utf8Like]]",
"attr.rust.derive": "Default, PartialEq, Eq",
"attr.rerun.scope": "blueprint"
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::HashSet;
use crate::dataframe_ui::HideColumnAction;
use crate::view_query_v2::QueryV2;
use re_chunk_store::{ColumnDescriptor, ColumnSelector};
use re_log_types::{TimeInt, TimelineName};
use re_log_types::{EntityPath, TimeInt, TimelineName};
use re_types::blueprint::{components, datatypes};
use re_viewer_context::{SpaceViewSystemExecutionError, ViewerContext};

Expand Down Expand Up @@ -168,7 +168,15 @@ impl QueryV2 {
.iter()
.map(|timeline_name| timeline_name.as_str().into())
.collect();
let selected_component_columns = component_columns.iter().cloned().collect::<HashSet<_>>();
let selected_component_columns = component_columns
.iter()
.map(|selector| {
(
EntityPath::from(selector.entity_path.as_str()),
selector.component.as_str(),
)
})
.collect::<HashSet<_>>();

let query_timeline_name = *self.timeline(ctx)?.name();
let result = view_columns
Expand All @@ -181,12 +189,16 @@ impl QueryV2 {
|| selected_time_columns.contains(desc.timeline.name())
}
ColumnDescriptor::Component(desc) => {
let blueprint_component_descriptor = components::ComponentColumnSelector::new(
&desc.entity_path,
desc.component_name,
);

selected_component_columns.contains(&blueprint_component_descriptor)
// Check against both the full name and short name, as the user might have used
// the latter in the blueprint API.
//
// TODO(ab): this means that if the user chooses `"/foo/bar:Scalar"`, it will
// select both `rerun.components.Scalar` and `Scalar`, should both of these
// exist.
selected_component_columns
.contains(&(desc.entity_path.clone(), desc.component_name.full_name()))
|| selected_component_columns
.contains(&(desc.entity_path.clone(), desc.component_name.short_name()))
}
})
.cloned()
Expand Down
11 changes: 7 additions & 4 deletions docs/snippets/all/views/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,24 @@
rr.init("rerun_example_dataframe", spawn=True)

# Log some data.
rr.log("trig/sin", rr.SeriesLine(color=[255, 0, 0], name="sin(0.01t)"), static=True)
rr.log("trig/cos", rr.SeriesLine(color=[0, 255, 0], name="cos(0.01t)"), static=True)
for t in range(0, int(math.pi * 4 * 100.0)):
rr.set_time_seconds("t", t)
rr.log("trig/sin", rr.Scalar(math.sin(float(t) / 100.0)))
rr.log("trig/cos", rr.Scalar(math.cos(float(t) / 100.0)))

# some sparse data
if t % 5 == 0:
rr.log("trig/tan_sparse", rr.Scalar(math.tan(float(t) / 100.0)))

# Create a Dataframe View
blueprint = rrb.Blueprint(
rrb.DataframeView(
origin="/trig",
# TODO(#6896): improve `DataframeQueryV2` API and showcase more features
query=rrb.archetypes.DataframeQueryV2(
timeline="t",
range_filter=rrb.components.RangeFilter(start=rr.TimeInt(seconds=0), end=rr.TimeInt(seconds=20)),
filter_by_range=(rr.TimeInt(seconds=0), rr.TimeInt(seconds=20)),
filter_by_event="/trig/tan_sparse:Scalar",
select=["t", "log_tick", "/trig/sin:Scalar", "/trig/cos:Scalar", "/trig/tan_sparse:Scalar"],
),
),
)
Expand Down

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,70 @@
from __future__ import annotations

from typing import Any

from ... import datatypes
from ...blueprint import components as blueprint_components, datatypes as blueprint_datatypes
from ...error_utils import catch_and_log_exceptions


class DataframeQueryV2Ext:
"""Extension for [DataframeQueryV2][rerun.blueprint.archetypes.DataframeQueryV2]."""

def __init__(
self: Any,
*,
timeline: datatypes.Utf8Like | None = None,
filter_by_range: tuple[datatypes.TimeInt, datatypes.TimeInt]
| blueprint_datatypes.FilterByRangeLike
| None = None,
filter_by_event: blueprint_datatypes.ComponentColumnSelectorLike | None = None,
apply_latest_at: bool = False,
select: list[blueprint_datatypes.ComponentColumnSelectorLike | datatypes.Utf8Like | str] | None = None,
):
"""
Create a new instance of the DataframeQueryV2 archetype.
Parameters
----------
timeline:
The timeline for this query.
filter_by_range:
If set, a range filter is applied.
filter_by_event:
If provided, the dataframe will only contain rows corresponding to timestamps at which an event was logged
for the provided column.
apply_latest_at:
Should empty cells be filled with latest-at queries?
select:
Selected columns. If unset, all columns are selected.
"""

if isinstance(filter_by_range, tuple):
start, end = filter_by_range
filter_by_range = blueprint_components.FilterByRange(start, end)

if filter_by_event is not None:
if isinstance(filter_by_event, str):
column = blueprint_datatypes.ComponentColumnSelector(spec=filter_by_event)
else:
column = filter_by_event

new_filter_by_event = blueprint_components.FilterByEvent(active=True, column=column)
else:
new_filter_by_event = None

with catch_and_log_exceptions(context=self.__class__.__name__):
self.__attrs_init__(
timeline=timeline,
filter_by_range=filter_by_range,
filter_by_event=new_filter_by_event,
apply_latest_at=apply_latest_at,
select=select,
)
return
self.__attrs_clear__()

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

Loading

0 comments on commit c738b89

Please sign in to comment.