Skip to main content

Saving and exporting

Writing a workspace to disk: a .scana file that keeps everything, or a CSV of one part of it. Both sit directly on the workspace.

The server writes the file

Every path on this page is resolved by the server, on the server's machine and with the server's permissions, not by your script. Against a remote server, a local path means nothing and the file lands on the far end. See Remote and shared instruments.

save​

Writes the whole workspace to a .scana: the captured data, the decoders and their configuration, the markers and the measurements.

workspace.save("/data/run-42.scana", timeout=600.0)

workspace.path # where it was saved, or None
workspace.dirty # True when there are unsaved changes

Opening a .scana​

Reopen one later with open(). No device needed.

open() returns once the capture is loaded

open() waits until the file is loaded. When it returns the capture is in the workspace, so there is no polling loop to write:

workspace = server.open("/data/run-42.scana")
workspace.capture.last_sample # the recording, not 0

A file the server cannot read raises at once rather than handing back an empty workspace: IoError in Python and NodeJS, Error::Io in Rust, and a NULL handle with ss_last_error() in C. A file that takes longer than the timeout to load raises Timeout instead (Error::Timeout, ss_status_Timeout).

export_csv​

Writes part of the workspace as CSV.

# Raw samples for two channels.
workspace.export_csv(
"/data/samples.csv",
source="samples",
channels=[0, 1],
)

# The decoded packets of one decoder.
workspace.export_csv(
"/data/packets.csv",
source="packets",
instances=[i2c.instance_id],
)

# A European-locale CSV, over a marker range.
workspace.export_csv(
"/data/run.csv",
source="hex",
separator=";",
decimal_comma=True,
from_marker=first,
to_marker=second,
)

The four sources:

sourceWhat it writes
samplesRaw logic samples for the channels you name. The largest by far.
rawThe decoders' item rows: every element they produced, with its span.
packetsThe Packet View: decoded packets with title and content.
hexThe Hex View: the byte stream the decoders produced.

Options:

OptionMeaning
channelsWhich channels to write. samples only.
instancesWhich decoder instances to write. The three decoded sources.
separatorField separator. Defaults to ,.
decimal_commaWrite 0,5 rather than 0.5, for European spreadsheets.
from_marker, to_markerRestrict the export to a marker range.
The workspace is frozen while it exports

A CSV export freezes the workspace: any command that would change it is refused with a Busy error until the export finishes. That includes commands from other clients, so the ScanaStudio window will look stuck. Exporting a long capture takes a while, which is why the default timeout is 600 s.

Calls in a row each get their own answer

Each save(), export_csv() and open() waits for the answer to its own request, so two exports issued one after the other both write their file. A call made while an export, from this client or another, still holds the workspace raises Busy (Error::Busy in Rust, ss_status_Refused in C) instead of waiting.

save(), open() and export_csv() block until the server is finished and cannot be cancelled. The timeout is the only way out: give the call a budget you are willing to wait, and handle the Timeout if it runs over.

ui_state​

A workspace carries a blob of client view state (zoom, cursors, whatever your own front end wants to remember). The server never reads it; it is written into the .scana and comes back with it.

workspace.set_ui_state('{"zoom": 4}', mark_dirty=False)
workspace.ui_state # the state this workspace was OPENED with
Reading it back does not return what you just wrote

ui_state reports the state the workspace was opened with: the server sends it when you attach and when a .scana is loaded. It is not an echo of set_ui_state. A value you have just written reads back here only after the workspace has been saved and reopened, or attached to afresh. Keep your own copy in memory if you need to read it during a session.

Pass mark_dirty of false for a change the user would not call unsaved work, such as moving a cursor rather than editing the capture.

In NodeJS, mark_dirty is a plain boolean second argument. An object passed there is truthy, so set_ui_state(state, { mark_dirty: false }) marks the workspace as modified.

Errors​

ErrorPython / NodeJSRustC
The server could not write or read the file: a bad path, a full disk, a cancellationIoErrorError::Ioss_status_Failed
Another export holds the workspace (save(), export_csv())BusyError::Busyss_status_Refused
The operation ran past its timeoutTimeoutError::Timeoutss_status_Timeout
source is not one of samples, raw, packets, hexValueError / RangeErrorError::Ioss_status_Failed

The source check runs in the SDK before anything is sent. In Python it is a plain ValueError and in NodeJS a RangeError, neither of which derives from ScanaStudioError.

ss_last_error() holds the server's reason for each failure in C.