Skip to content

xy: Add mipmap-based downsampling for XY data providers#422

Draft
MatthewKhouzam wants to merge 1 commit into
eclipse-tracecompass:masterfrom
MatthewKhouzam:mipmap
Draft

xy: Add mipmap-based downsampling for XY data providers#422
MatthewKhouzam wants to merge 1 commit into
eclipse-tracecompass:masterfrom
MatthewKhouzam:mipmap

Conversation

@MatthewKhouzam

@MatthewKhouzam MatthewKhouzam commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

What it does

Introduce max-per-bucket aggregation backed by pre-computed mipmap levels in the state system. This replaces trivial point-sampling with spike-preserving downsampling that guarantees visual correctness at every zoom level.

New components:

  • AbstractXYStateProvider (provisional API): base state provider with ergonomic mipmap helpers (modifyMipmapAttribute, incrementMipmap*)
  • TimeMipmapFeature: time-based mipmap with power-of-10 levels (10ns, 100ns, 1us, 10us, ...) aligned to natural time units
  • MipmapXYQueryHelper: internal utility that auto-detects mipmap sub-attributes and replaces Y values with queryRangeMax per bucket

Integration:

  • AbstractTreeCommonXDataProvider.fetchXY() auto-enhances results
  • AbstractTreeGenericXYCommonXDataProvider.fetchXY() same (timestamps only)
  • AbstractTreeDataProvider exposes getIdToQuark() for ID-to-quark mapping

Migration (proof of concept):

  • CounterStateProvider now extends AbstractXYStateProvider
  • Uses mipmap helpers instead of StateSystemBuilderUtils
  • State system version bumped to trigger rebuild

How to test

Open some xy plots.

Follow-ups

Make all XY plots use delta based storage.

Review checklist

  • As an author, I have thoroughly tested my changes and carefully followed the instructions in this template

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 98dfc07e-e247-4ed3-96c8-11951c0fd7f4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@MatthewKhouzam

Copy link
Copy Markdown
Contributor Author

@arfio, @JonatanAntoni fyi

Introduce max-per-bucket aggregation backed by pre-computed mipmap
levels in the state system. This replaces trivial point-sampling with
spike-preserving downsampling that guarantees visual correctness at
every zoom level.

New components:
- AbstractXYStateProvider (provisional API): base state provider with
  ergonomic mipmap helpers (modifyMipmapAttribute, incrementMipmap*)
- TimeMipmapFeature: time-based mipmap with power-of-10 levels
  (10ns, 100ns, 1us, 10us, ...) aligned to natural time units
- MipmapXYQueryHelper: internal utility that auto-detects mipmap
  sub-attributes and replaces Y values with queryRangeMax per bucket

Integration:
- AbstractTreeCommonXDataProvider.fetchXY() auto-enhances results
- AbstractTreeGenericXYCommonXDataProvider.fetchXY() same (timestamps only)
- AbstractTreeDataProvider exposes getIdToQuark() for ID-to-quark mapping

Migration (proof of concept):
- CounterStateProvider now extends AbstractXYStateProvider
- Uses mipmap helpers instead of StateSystemBuilderUtils
- State system version bumped to trigger rebuild

This code was made with a tightly guided assistance from Claude Sonnet 4.6

Change-Id: I2088657ba1702f0e101b9debc37ee94ee06b4efb
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
@JonatanAntoni

Copy link
Copy Markdown

@thorstendb-ARM

@JonatanAntoni

JonatanAntoni commented Jul 7, 2026

Copy link
Copy Markdown

The issue we are looking to solve can be reproduce with e.g. with a sampled sine wave like this:

Bildschirmfoto 2026-07-07 um 14 37 18

Zooming out, so that one or more periods of the sine wave collapse onto a single pixle the current downsampling causes display effects like this:

Bildschirmfoto 2026-07-07 um 14 37 07

Instead, something like the following would be better for us:
Bildschirmfoto 2026-07-07 um 14 53 41

@MatthewKhouzam

MatthewKhouzam commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Ah, this makes more sense. it is an interesting problem... Basically how would you like to see it solved? we can make an "envelop" per pixel. I usually look at an oscilloscope as a reference, and what is shown above is how it would display it.

@JonatanAntoni

Copy link
Copy Markdown

Here is how I solved this in my TypeScript TSP implementation to get to the latest picture:

  1. Bucketize the whole sample set to fixed time boundaries that don't change when panning the view.
  2. For each bucket that is (partially) within the selected view range, select four values: first, min, max, and last.

Ultimately, this leads to a factor 4 oversampling. I.e., if the client requests 1000 samples, this method actually sends back 4000 samples. The current graph implementation then results drawing 4 samples onto the same horizontal position. Of course, this is wasting some bandwidth and there might be a more elegant solution as well.

@MatthewKhouzam

Copy link
Copy Markdown
Contributor Author

Now oversampling works too. The mipmap and oversampling offer two solutions to the problem. What you're proposing could still miss a spike, but it's less likely. Let's discuss/nerd out on wednesday's meeting.

@MatthewKhouzam

Copy link
Copy Markdown
Contributor Author

Here is an illustration of all three strategies as per my understanding.

As-is
sampling-aliasing
With oversampling, much better.
oversampling
With mipmap, it's garanteed not to lose the max
mipmapping

@thorstendb-ARM

thorstendb-ARM commented Jul 8, 2026

Copy link
Copy Markdown

Max-per-bucket preserves positive spikes, but it does not make waveform rendering visually correct.

For waveforms, a bucket needs to retain the envelope and continuity information: min, max, and the exit/last value used to connect to the next bucket. Without that, aliasing is still possible because the renderer may connect representative points in a way that misrepresents the original curve.

I attached a graphic showing an expanded view of compressed buckets.
image

@JonatanAntoni

Copy link
Copy Markdown

@MatthewKhouzam, my approach isn't actually oversampling as I do not pick equally spaced samples from the original signal. We are picking the highest and lowest Y-values from a bucket regardless of their X-values and put them together on the same scaled X-value. Its similar to the mipmap-approach but with more values so that positive and negative extrema are preserved.

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.

3 participants