############################# Using the ``ln_scope`` Viewer ############################# .. index:: pair: user guide; ln_scope What this is about ================== ``ln_scope`` is a GTK-based live signal viewer for LN topics. It is meant to be used like a lightweight oscilloscope for LN data streams: users can open one or more traces, subscribe to arbitrary primitive fields, inspect values with hover markers, configure trigger conditions, and store complete scope sessions for later reuse. Starting ``ln_scope`` ===================== The scope can be started directly as a Python module: .. code-block:: bash python3 -m links_and_nodes.scope It also accepts startup signal specifications and saved scope states: .. code-block:: bash python3 -m links_and_nodes.scope topic1:field1 python3 -m links_and_nodes.scope --trace topic1:field1 --trace topic2:field2 python3 -m links_and_nodes.scope --load-state my_scope.pkl python3 -m links_and_nodes.scope --load-state my_scope.pkl --load-state-without-data Recorded data can also be replayed directly from an ``lnrecorder`` database: .. code-block:: bash python3 -m links_and_nodes.scope --lnrdb ./my_recording.lnrdb The default display refresh rate is 50 Hz, if this is too much for your system you can set the environment variable :envvar:`LN_SCOPE_DEFAULT_DISPLAY_RATE` to another rate, like 10 for 10 Hz. Offline Replay from ``lnrdb`` ============================= When started with ``--lnrdb``, ``ln_scope`` does not connect to ``ln_manager``. Instead, it reads topic tables from the given lnrecorder database and replays them through the normal scope trace pipeline. The toolbar then shows three extra replay controls: - a play toggle button - a horizontal seek slider - a position label showing the current percentage and replay time in seconds The displayed replay time starts at ``0.0 s`` at the first timestamp of the recording and increases relative to that recording start. Replay-specific behavior: - the topic browser on the left follows the replay time - topics only appear while they are active in the recording - if a topic disappears and later reappears, the browser updates accordingly - if a topic name reappears with a different message definition, the currently active recorded incarnation is the one shown and used for new subscriptions Seeking jumps to an arbitrary point in the recording. After a seek, existing trace displays are preloaded with the most recent recorded data needed for their configured ``record seconds`` history, so users can inspect the state immediately without waiting for replay to run forward again. Trace Displays ============== Each trace display is independent and owns its own topic subscriptions and sample buffers. A single trace can combine signals from multiple topics, and multiple traces may subscribe to the same LN topic without sharing state. This remains true in offline replay mode as well: each trace keeps its own private replay-backed subscriptions and buffers. Each trace header offers quick access to: - selecting the trace - minimizing, maximizing, or removing it - detaching the trace into its own top-level window - opening the trace settings window - opening the per-trace logger control window The header context menu also provides direct access to settings, logger control, and trace removal. Trace Layout and Drag/Drop ========================== The main trace area uses a nested split layout similar to a tiling window manager. The top level starts as a horizontal split, so newly added traces appear next to each other from left to right by default. Traces can be rearranged by dragging their header bars onto other traces: - dropping on a left or right edge inserts the dragged trace into the existing horizontal split container at that side - dropping on a top or bottom edge inserts the dragged trace into the existing vertical split container at that side - dropping on the left or right third of a trace creates a new nested horizontal split around that trace - dropping on the top or bottom third of a trace creates a new nested vertical split around that trace This means: - edge drops extend an already existing row or column - third-area drops create a new inner split container Split containers collapse automatically when they contain only a single child, except for the permanent top-level horizontal root container. A toolbar toggle can show colored split borders to visualize the current layout: - orange border: horizontal split container - green border: vertical split container Detached Trace Windows ====================== Each trace header also has a detach toggle button. When enabled, that trace is removed from the main split layout and shown in its own top-level window. Detached traces: - keep their signals, trigger state, and logger control like normal traces - can be attached back into the main layout by toggling the detach button off - can still be minimized - are removed entirely if the detached top-level window is closed directly Detached state is also part of the saved scope snapshot. Signals and Settings ==================== The trace settings window allows configuring: - horizontal and vertical scaling - subscriber rate and buffer count - signal visibility, colors, scale, and offset - trigger source, threshold, edge, and history settings - shared x-axis following from another trace - trigger following from another trace - synthetic math signals derived from existing signals Math signals are shown in the same signal tree as normal signals. They are configured through the math editor on the right side of the settings window. Interaction =========== The scope has several direct mouse and modifier interactions. The most useful ones are the following. Trace header ------------ - Left double-click opens the trace settings window. - Right click opens the trace header context menu. - Dragging the header is used for trace layout drag/drop in the split layout. Drawing area ------------ - Moving the mouse shows a hover crosshair on the local trace and synchronized time markers on the other visible traces. - Left drag pans the current time and value view. - Right drag zooms the current time and value view around the drag origin. - Mouse wheel zooms the value axis. - ``Ctrl`` + mouse wheel zooms the time axis. - ``Ctrl`` + ``Shift`` + mouse wheel zooms time and value together. - ``Shift`` + left drag creates a shared time-span selection that is rendered in all visible traces. - ``Shift`` + left drag near an existing selection edge adjusts only that edge instead of starting a new selection. - Dragging the red trigger line or the red off-screen trigger triangles changes the trigger threshold or trigger position directly. - Dragging the left-side offset triangle of a signal changes that signal's display offset. - Double-clicking that offset triangle resets the corresponding signal offset. Buttons ------- - ``Ctrl`` while toggling the per-trace ``rec`` button applies the new recording state to all traces. The selected time span is shared globally across the scope and is rendered in all visible traces. Triggering and History ====================== Each trace can either trigger locally from one of its signals or follow the trigger events of another trace. Trigger captures are stored as history items that can later be inspected in ``Live`` / ``History`` mode. To configure a local trigger starting from an empty scope, use the following sequence: 1. Add a trace with the toolbar ``add trace`` button. 2. Add at least one signal to that trace by dragging a field from the topic browser into the trace, or by starting the scope with a ``TOPIC:FIELD`` argument. 3. Open the trace settings window, for example by double-clicking the trace header. 4. In the signals tree, choose which signal should act as the trigger source: double-click the ``Trigger`` column of that signal until the wanted trigger mode appears. 5. Set the trigger edge and threshold in the settings window, or drag the red trigger marker directly in the trace view. 6. Adjust ``record seconds`` and ``trigger position`` so the trace keeps the desired amount of pre-trigger and post-trigger data. 7. Enable ``trigger enabled`` in the trigger frame. 8. Wait for a matching signal transition, or use ``force trigger`` in the trigger frame to create one immediately. 9. After trigger events were captured, switch the trace between ``Live`` and ``History`` mode to inspect the stored trigger history items. Only one local trigger source is active for a trace at a time. Alternatively, instead of enabling local triggering, a trace can be configured to follow the trigger events of another trace. Trigger snapshots can also be included when a complete scope state is saved. Logger Control ============== Each trace has its own LN-daemon logger control window. It allows configuring which topics of that trace should be logged, starting and stopping the logger, downloading the captured data, and unpacking it into a notebook context for interactive analysis. The logger control estimates an observed topic rate, keeps a configurable max rate per topic, and derives the ring-buffer sample count from the desired recording duration. Saving and Loading Scope State ============================== The main toolbar provides ``save`` and ``load`` actions for complete scope snapshots. These snapshot files use a binary pickle format and can contain: - trace layout and selected trace - signal selections and per-signal display settings - trigger and shared-master configuration - shared time-span selection - optionally the currently buffered live data and trigger history When a scope state is loaded, all traces start with recording disabled so the restored data remains visible until the user explicitly resumes collection.