Fix derived-plot alignment and cursor stability under zoom/EOF#3
Open
Theleifless wants to merge 17 commits into
Open
Conversation
TracePlot::paintMid was computing its own samples-per-column locally from sampleRange.length() / rect.width(). When the view range gets clamped to a small file (smaller than the natural fftSize/zoomLevel span of the viewport), the spectrogram still uses fftSize/zoomLevel while TracePlot stretches its samples across the whole viewport -- so the two panels visibly disagree on the time axis. Push the view's samples-per-column into each TracePlot (via a new TracePlot::setSamplesPerColumn) when it is added and whenever setFFTAndZoom recomputes the time scale. Falls back to the legacy local computation when no value has been set so existing standalone users keep their previous behaviour. Reproduces with any short SigMF capture at non-default zoom: open the file, right-click -> Add derived plot -> Add amplitude, then zoom in. Before this change the trace fills the viewport while the spectrogram occupies a fraction of it; after, both panels stop at the same x-pixel.
InputSource::getSamples returns nullptr when start + length exceeds sampleCount. TracePlot::drawTile would then bail without emitting an image, so the tile remained fully transparent. Symptom: when zoomed in, samplesPerTile can be larger than the entire file, so even the first tile gets a null buffer and the trace plot vanishes entirely. The spectrogram handles this exact case by filling with -inf (renders black); TracePlot was the outlier. Clamp the request to what is actually available on the source, shrink the draw rect proportionally so the visible samples occupy their natural pixel range, and always emit the image so QPixmapCache caches it (no busy-loop retry).
getLine() centred the FFT on `sample` but bailed to a column of -inf whenever first_sample + fftSize exceeded the file size. That made the spectrogram visibly stop fftSize/2 samples short of the trace plots' right edge, since the last fully-centred FFT lives at sample EOF - fftSize/2. Get whatever samples are available, zero-pad the rest of the FFT buffer, then run the same windowing / FFT / dB pipeline. The last columns get slight spectral leakage from the padding boundary, but the spectrogram now ends at the same x-pixel as the trace plot and the user can actually see what's happening at the end of a short capture. The pre-existing head-of-file clamp (and its -inf bail-out when first_sample >= EOF) is preserved.
The cursors store their position in viewport pixels. setFFTAndZoom changes samplesPerColumn but did not re-anchor the cursors, so the same pixel pair now spanned a different sample count. The "Symbol rate" / "Period" readouts in the Time selection panel would silently drift just because the user zoomed -- a sharp foot-gun when the readout is being used to measure something. Snapshot the cursor's absolute sample range at the top of setFFTAndZoom and re-place the cursors on the new pixel grid at the end, after updateView() has already settled the scrollbars. The final write also overrides any stale value left by the cursorsMoved signal cascade that fires when setSelection() temporarily reads back the rounded-to-integer-column pixel position.
# Conflicts: # CMakeLists.txt # src/spectrogramplot.h
Annotations without a presentation:color field yield an empty QString. The color-format check called sigmf_color.at(0) before testing length; under Qt6 an empty QString has a null data pointer, so at(0) dereferenced null and crashed when opening such a recording. Check length() == 9 first so the && short-circuits before at(0). Co-Authored-By: Claude Opus 4.8 (1M context) <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.
Four related bugs that surface together when inspecting short SigMF captures
with a derived plot (amplitude / IFR / ...) panel added beneath the spectrogram.
Each commit is self-contained.
1. TracePlot drew on a different x-scale than the spectrogram
When
viewRangegot clamped to a small file,TracePlot::paintMidcomputedsamplesPerColumn = sampleRange.length() / rect.width()while the spectrogramused
fftSize / zoomLevel. The two panels drew the same samples at differentx positions. PlotView now pushes its global samples-per-column into each
TracePlot via a new
setSamplesPerColumnsetter (with a fallback to thelegacy local computation for any non-PlotView caller).
2. TracePlot vanished at high zoom
samplesPerTilecould exceed the file size,InputSource::getSamplesreturned
nullptr, anddrawTilereturned without emitting an image — soQPixmapCache never got a tile and the panel stayed transparent. Now
drawTileclamps the request to what the source actually has, shrinks the draw rect
proportionally so the visible samples occupy their natural pixel range, and
always emits the image.
3. Spectrogram clipped fftSize/2 samples before EOF
The centred FFT couldn't be computed for the last
fftSize/2samples;getLinefilled the column with-inf. The spectrogram visibly ended shortof the trace plots' right edge.
getLinenow zero-pads the partial bufferat EOF so the spectrogram and trace plots stop at the same x-pixel.
4. Cursors lost their sample range under zoom
Cursors store viewport-pixel positions;
setFFTAndZoomchangedsamplesPerColumnwithout re-anchoring them, so the "Symbol rate" / "Period"readout drifted just because the user zoomed.
setFFTAndZoomnow snapshotsthe cursors' absolute sample range at the top and re-places the cursors on
the new pixel grid at the end, after
updateView()has settled thescrollbars.
Test plan
right-click → Add derived plot → Add amplitude, Ctrl-scroll to zoom from
1× to maximum. Both panels stay aligned at every zoom level and the trace
remains visible end-to-end.
"Symbol rate" / "Period" readout, zoom in and out. Readout stays put.
reaches the same x-pixel as the derived plot.