Skip to content

Downloader analytics v2: multi-plot workspace, state timeline, fault decoding, and docs#78

Merged
haoruizhou merged 34 commits into
mainfrom
downloader-analytics
Jul 17, 2026
Merged

Downloader analytics v2: multi-plot workspace, state timeline, fault decoding, and docs#78
haoruizhou merged 34 commits into
mainfrom
downloader-analytics

Conversation

@haoruizhou

@haoruizhou haoruizhou commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Adds the Analysis tab to the data-downloader with multi-signal Plotly plots, vehicle state timeline with PM100 fault decoding, CSV export, and comprehensive documentation.

Backend

  • POST /api/series: density-aware multi-signal time-series endpoint (raw or time-bucketed envelope)
  • POST /api/states: vehicle state lane segments and PM100 fault interval decoding
  • signal_choices() in dbc_utils for DBC VAL_ label lookup

Frontend

  • AnalysisWorkspace orchestrator with run/custom range selection
  • AnalysisPlotStack with multi-plot groups, dual Y-axes, linked zoom, and drag-and-drop signal assignment
  • AnalysisSignalPicker with DBC-grouped signals, click-to-toggle, and drag-to-assign
  • AnalysisStateTimeline with collapsible car/inverter/fault lanes and click-to-zoom
  • PlotAssignMenu accessible combobox for plot reassignment
  • useSeriesData hook with 300ms debounce, LRU cache (1M point budget), retry, and clear
  • Plot layout persistence per season in localStorage with stale-signal pruning
  • CSV export with envelope min/max/avg column expansion

Tests: 178 total (48 backend + 130 frontend), all passing

Docs: Analytics feature documentation added to data-downloader README

Allocate generation when a range is queued, clear stale errors immediately, and reject superseded state updates so in-flight responses cannot overwrite the current UI.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 61d5f72d11

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

def build_envelope_sql(table: str, signal: str) -> str:
column = _quoted(signal)
return (
"SELECT time_bucket(%(bucket)s::interval, time) AS bucket, "

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Anchor envelope buckets to the requested range

When a dense signal switches to envelope mode and the requested start is not aligned to the computed bucket interval, time_bucket labels the first aggregate with TimescaleDB's global bucket boundary, which can be before payload.start. The analysis plot clamps the x-axis to the requested [start, end], so that first aggregate can be clipped from the visible range, while CSV exports can contain out-of-range timestamps. Anchor buckets to the request start (or clamp/center returned bucket timestamps) so envelope data represents the selected window correctly.

Useful? React with 👍 / 👎.

const movedRight = new Set(
layout.flatMap((g) => g.rightAxis.filter((s) => unique.includes(s))),
);
const removed = removeSignals(layout, new Set(unique));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve the target plot during self-assignments

When the dragged/assigned payload contains every signal currently in the target plot, such as dropping a selected one-signal plot back onto itself or dropping a message group that includes the target's only signal, removeSignals prunes the target before the later append step. Since the target id no longer exists in removed, the assignment returns without re-adding those signals, making them disappear from the layout. Handle no-op/self-target cases or keep the target group until after the destination is rebuilt.

Useful? React with 👍 / 👎.

const TRACK_STYLE = { marginRight: `${PLOT_AREA_MARGIN.right}px` } as const;

const COLLAPSE_KEY = "analysis-timeline-collapsed";
const HOVER_DELAY_MS = 50;
# Conflicts:
#	server/installer/data-downloader/backend/app.py
#	server/installer/data-downloader/frontend/src/analysis/plot-traces.test.ts
#	server/installer/data-downloader/frontend/src/analysis/plot-traces.ts
#	server/installer/data-downloader/frontend/src/api.ts
#	server/installer/data-downloader/frontend/src/components/AnalysisPlotStack.test.tsx
#	server/installer/data-downloader/frontend/src/components/AnalysisPlotStack.tsx
#	server/installer/data-downloader/frontend/src/components/AnalysisSignalPicker.test.tsx
#	server/installer/data-downloader/frontend/src/components/AnalysisSignalPicker.tsx
#	server/installer/data-downloader/frontend/src/components/AnalysisWorkspace.test.tsx
#	server/installer/data-downloader/frontend/src/components/AnalysisWorkspace.tsx
#	server/installer/data-downloader/frontend/src/components/sensor-palette.ts
#	server/installer/data-downloader/frontend/src/styles.css
#	server/installer/data-downloader/frontend/src/test-setup.ts
@haoruizhou haoruizhou changed the title Downloader analytics Downloader analytics v2: multi-plot workspace, state timeline, fault decoding, and docs Jul 17, 2026
@haoruizhou
haoruizhou merged commit bdcaa43 into main Jul 17, 2026
11 checks passed
@haoruizhou
haoruizhou deleted the downloader-analytics branch July 17, 2026 14:31
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.

1 participant