Skip to content

Use color bar with vertically split proportion to indicate the percentage of states in a merged region. - #12835

Open
MarkChenYutian wants to merge 3 commits into
rerun-io:mainfrom
MarkChenYutian:contrib/yutian_chen/issue_12829
Open

Use color bar with vertically split proportion to indicate the percentage of states in a merged region.#12835
MarkChenYutian wants to merge 3 commits into
rerun-io:mainfrom
MarkChenYutian:contrib/yutian_chen/issue_12829

Conversation

@MarkChenYutian

Copy link
Copy Markdown

Related

What

When a lane in the state timeline view has many state changes packed too tightly to render individually (narrower than 4px on screen), they're folded into a single merged region. Previously this merged region rendered as a flat, uniformly-colored box labeled "N states" — all information about which states were present, and for how long, was lost.

This PR replaces that flat box with a duration-weighted stacked color chart: the merged region's screen width is split into fixed-width time buckets (~3px each, capped at 512 buckets), and each bucket is rendered as a small stacked column where every distinct state's color contributes a height proportional to the fraction of that bucket's time span it actually occupied. This lets a densely collapsed region still visually convey which state dominated a given interval, instead of hiding that information behind a generic gray box.

Details:

  • The stacking order of colors within a bucket is sorted alphabetically by state label (rather than by first-seen order), so it stays stable across adjacent merged regions and while panning/zooming — first-seen order would otherwise cause the stack to visually flip depending on which phase happened to scroll into view first.
  • The "N states" label is no longer drawn on the region itself (it competed visually with the chart); the phase count is still available via the existing hover tooltip.
  • examples/rust/state_timeline_example now logs a densely-packed lane so the new rendering is visible by default without having to zoom into a tiny slice of the timeline.
  • Added/updated the state_timeline_merge_small_phases snapshot test to cover the new rendering.

Screenshots

States when compactly folded

Screenshot 2026-07-05 at 1 09 32 PM

States when zoomed in

Screenshot 2026-07-05 at 1 10 09 PM

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! Thanks for opening this pull request.

Because this is your first time contributing to this repository, make sure you've read our Contributor Guide and Code of Conduct.

@Wumpf
Wumpf requested a review from aedm July 15, 2026 09:22
@MarkChenYutian

Copy link
Copy Markdown
Author

Hi @aedm and @Wumpf , appreciate your notice on this PR! could you review this when you guys are free? we do want this feature a lot for our current deployment use case and don't want to maintain a fork. thanks!

@Wumpf

Wumpf commented Jul 21, 2026

Copy link
Copy Markdown
Member

sorry for the delay! @aedm wanted to have a look at this but he's out on vacation this & next week and didn't manage to do so in time. I'll see if I can find to have a look myself or get it reassigned

@Wumpf Wumpf left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some nits, but there's a more high level problem here: it's not stable over time! Right now to see that one has to move in and scroll horizontal, but once the view supports time ranges and follows the time cursor like the time series view does by default on larger recordings (!) this becomes a serious issue as it causes a lot of flickering:

flicker.on.horizontal.move.mov

Comment thread crates/viewer/re_view_state_timeline/src/view_class.rs Outdated
Comment thread crates/viewer/re_view_state_timeline/src/view_class.rs Outdated
let overlap_end = phase_end.min(bucket_t1);
if overlap_end > overlap_start
&& let Some(content) = &phases[p].content
&& let Some(color_idx) = colors.iter().position(|c| c == &content.color)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm this gets n-squary computational wise. Makes me a bit uneasy. But probably fine; building up a lookup table is likely overkill 🤔

@MarkChenYutian

Copy link
Copy Markdown
Author

Thanks for feedback @Wumpf ! Yes I agreed that the flicker is tricky - do you think it would be a good solution if I fix the partitioning (instead of binning based on pixel space I bin on absoluate log tick / log time_ns)? Do you have any suggestion on this?

MarkChenYutian and others added 2 commits July 24, 2026 14:17
Co-authored-by: Andreas Reich <r_andreas2@web.de>
Co-authored-by: Andreas Reich <r_andreas2@web.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show time share of collapsed states

2 participants