From 3e0d0de3258c933a2a07fa0e2e9c6c1809817ebc Mon Sep 17 00:00:00 2001 From: Martino Ferrari Date: Sun, 4 Oct 2026 15:09:05 +0200 Subject: [PATCH] docs: help pages for export, sessions and the status bar --- src/help/12-export.txt | 31 ++++++++++++++++++++++++ src/help/13-sessions.txt | 34 ++++++++++++++++++++++++++ src/help/14-status.txt | 36 ++++++++++++++++++++++++++++ src/help/udpscope-help.gresource.xml | 3 +++ src/help_window.cpp | 3 +++ 5 files changed, 107 insertions(+) create mode 100644 src/help/12-export.txt create mode 100644 src/help/13-sessions.txt create mode 100644 src/help/14-status.txt diff --git a/src/help/12-export.txt b/src/help/12-export.txt new file mode 100644 index 0000000..2b7c8a0 --- /dev/null +++ b/src/help/12-export.txt @@ -0,0 +1,31 @@ +Saving and export + +Export writes the visible range of every plotted trace to a file: NumPy .npy or +.csv, chosen by the extension you type. + +How to reach it + +Export visible range… in the overflow menu, or Ctrl+E. A file chooser asks where; +the format follows the path's extension. + +Worth knowing + +• The table is collected at the moment you click, not when the chooser returns. A live view keeps + scrolling while a dialog is up, so a late collection would write a window you never saw. +• The rows are the stored samples, never the LOD buckets the plot draws from. A row count + far below the span times the stored rate means something cut the table from the pyramid. +• The stored rate is not always the wire rate. A window long enough to need decimation is stored + averaged at a lower rate, and the export carries that — read the status bar's ⓘ popover + for the figure before trusting a sample count. +• Two time columns. time is the display timeline (relative to the trigger edge while an + event is held) and stream_time is the source's own clock. Both are strictly increasing + and evenly spaced; duplicate or backwards stamps would mean the file held two clocks. +• An export taken mid-capture writes the partly filled window that is on screen, which is + shorter than the event span. Export outside a capture if you want the whole event. + +Example + +A 2 s window at 10 kS/s over 3 traces writes 20001 rows and 5 columns +(time, stream_time, three signals). The .npy is +64·⌈(10+len(header)+1)/64⌉ + rows·(16 + 4·cols) bytes. Read it back with +pd.DataFrame(np.load(path)). diff --git a/src/help/13-sessions.txt b/src/help/13-sessions.txt new file mode 100644 index 0000000..22cec67 --- /dev/null +++ b/src/help/13-sessions.txt @@ -0,0 +1,34 @@ +Sessions and settings + +udpscope stores one session file per source, so reopening a source gives you the scope you +closed. There is no global preferences file: the session is the settings. + +How to reach it + +Nothing to open — the file is written as you work. Its path is in the About dialog, and the +directory is $XDG_CONFIG_HOME/udpscope, or ~/.config/udpscope when that is +unset. Each file is named <host>_<port>.toml. + +Worth knowing + +• What a session persists: the time window, the rows and each row's slot signals, the + calibration, which signals are enabled, the math channels with their graphs, and the + measurements pane. +• Signal identity is the name throughout, because a new CONFIG renumbers the channels. +• A file written by a run against a source whose streamer was down would name no signals at all, + so such a run does not write: a configured session is never overwritten by a run that + configured nothing. +• The multicast group and the interface live inside the file, because its name cannot + carry them. A file from an older build has neither key and loads as unicast on the default + route. +• The startup chooser lists only files that name at least one signal, which is what keeps it the + sources you configured rather than every port you have ever tested against. +• Deleting a file is a supported way to start a source over; the chooser's × does + exactly that. + +Example + +Connect to 127.0.0.1:8000, drop three signals on row 1 and set a 2 s window. +~/.config/udpscope/127.0.0.1_8000.toml now holds rows=1 window_s=2 with +signals = ["sine", "ramp", "noise", ""], and the next run reports +layout loaded from …/127.0.0.1_8000.toml with those signals already acquired. diff --git a/src/help/14-status.txt b/src/help/14-status.txt new file mode 100644 index 0000000..bee3e04 --- /dev/null +++ b/src/help/14-status.txt @@ -0,0 +1,36 @@ +Status bar and diagnostics + +The status bar is two tiers. The bar itself is one glance line — the state, the rate and the +window — and everything else is behind the ⓘ button at its right-hand end. + +How to reach it + +The bar is always visible under the plot. Click ⓘ for the detail popover. + +Worth knowing + +• The badge is one glyph in three colours: lit and dim alternating means data is arriving, and a + steady idle colour means it is not. A badge that never blinks is not a working badge. +• The state field is one word from a fixed set: live, paused, armed, + capturing, event held, disarmed. In trigger mode the bar adds + exactly one more field, how long ago the last event was. +• Nothing on the bar may change width with the stream, because the bar sits directly above the + plot and a wider label would relayout it. That is why the rate collapses to one figure or a + range rather than listing per channel, and why an elapsed time steps to a coarser unit instead + of growing digits. +• gaps counts packets the receiver knows it missed. It is the number that matters: a + non-zero count means samples are absent from the buffer, not merely late. +• reconnects counts sessions re-established with the source. Over unicast a climbing + count usually means a second client is taking the source's single session. +• The starvation notice — connected, but no new frames in the last second — is that same + situation seen from the other side. Pointing the app at a port where nothing answers produces + it too. +• stored versus wire in the popover is the decimation. They differ exactly + when the window is too long to store at full rate. + +Example + +The bar reads ● live · 10.0 kS/s · 2 s window. Behind ⓘ: +Stream connected, configured / packets 717 · frames 716 · gaps 0 / 3 signals · 3 channels, +Buffer 200.0 MB · 1677 s span · time x1 / stored 10.0 kS/s (wire 10.0 kS/s), +Plot 1 3 traces · 195000 samples, Reconnects 0. diff --git a/src/help/udpscope-help.gresource.xml b/src/help/udpscope-help.gresource.xml index 3a19f3a..6a8e108 100644 --- a/src/help/udpscope-help.gresource.xml +++ b/src/help/udpscope-help.gresource.xml @@ -20,5 +20,8 @@ 09-cursors.txt 10-measurements.txt 11-math.txt + 12-export.txt + 13-sessions.txt + 14-status.txt diff --git a/src/help_window.cpp b/src/help_window.cpp index 178d1c9..954ec92 100644 --- a/src/help_window.cpp +++ b/src/help_window.cpp @@ -41,6 +41,9 @@ constexpr HelpPage kPages[] = { {"Analysis", "Cursors", "/org/udpscope/help/09-cursors.txt"}, {"Analysis", "Measurements", "/org/udpscope/help/10-measurements.txt"}, {"Analysis", "Math channels", "/org/udpscope/help/11-math.txt"}, + {"Output and state", "Saving and export", "/org/udpscope/help/12-export.txt"}, + {"Output and state", "Sessions and settings", "/org/udpscope/help/13-sessions.txt"}, + {"Output and state", "Status bar and diagnostics", "/org/udpscope/help/14-status.txt"}, }; constexpr int kPageCount = static_cast(sizeof(kPages) / sizeof(kPages[0]));