Render trace plots by sample density - #410
Merged
Merged
Conversation
Full-length recordings hold millions of samples per trace, which Bokeh shipped to the browser in full and rendered point by point. On a one-hour TDT session (3,704,960 samples) the Step-3 preprocessing view pushed 296 MB over the websocket and took ~155 s to paint, during which the tab was frozen and the plots showed as empty boxes. Every site switch or table edit repeated the cost. Wrap the trace curves in downsample1d so the full arrays stay server-side and only the samples the plot is wide enough to show are sent, re-derived on every zoom or pan. The m4 algorithm keeps the minimum, maximum, first and last sample of each pixel column, so the drawn line matches plotting every sample and a one-sample artifact spike stays visible at any zoom level -- which matters here because these plots exist to find artifacts. The peak markers in the transients view are left at full resolution. The same session now paints in 258 ms and transfers 0.2 MB, with an identical y-axis range. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The plot builders now return shaded images rather than curves, so assertions that read sample values off a curve read the image's extent instead. Replace the m4-line tests with test_shading.py, which covers the property the change turns on: a one-sample spike is drawn in exactly one pixel column while the baseline fills every column, so a transient stays visible without being given the same weight as the noise band. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
pauladkisson
added a commit
that referenced
this pull request
Aug 6, 2026
The tonic pages predated PRs #410/#413/#414 and were the last ones still using the patterns those replaced. Define Tonic Epochs now mirrors Select Artifact Windows: one form row per window (label, numeric bounds nudgeable with the arrow keys, delete button) instead of a fixed three-row Tabulator, an "Add epoch" button, a column header, and an empty-state hint. Both pages' plots stack z-score and dF/F on a shared, linked time axis, stretch to the tab width, and render by per-pixel sample density, so a full-length recording no longer ships every sample to the browser. Editing a bound repaints the shaded spans through a pipe rather than re-aggregating the traces. The signal toggle is gone, since both traces are now shown at once. Windows saved on disk are reloaded when the page reopens, so a revisit shows the current definitions rather than a blank table. build_control_signal_fit's panel builder is extracted as _shaded_panel and shared with the new build_stacked_traces. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow up to #401
Details (AI-generated)
Step 3's preprocessing view sent every sample of every trace to the browser. On a one-hour TDT session (3,704,960 samples per trace) that was 296 MB over the websocket and ~155 s of frozen tab before anything painted, which read as a blank plot. The same page now paints in ~130 ms.
Trace plots are now rendered by per-pixel sample density (
datashade) instead of point-by-point lines. The full arrays stay server-side and re-aggregate on zoom and pan, so no sample is dropped and a one-sample artifact spike stays visible at any zoom level. Density rather than a reduced line matters here: with millions of samples in a few hundred pixel columns, a line through each column's minimum and maximum gives the noise band and a real transient identical weight, which is the distinction these plots exist to show.Affects the artifact-marking and artifact-review plots, the z-score/dF-F review, and the transients peak view.
Relates to #402 and #403.
🤖 Generated with Claude Code