Writing the visible range of every plotted trace to NumPy, CSV or MDF 3.30, and what each format carries. Martino Ferrari Saving and export

Export writes the visible range of every plotted trace to a file: NumPy .npy, .csv, or MDF 3.30 (.mf3 or .mdf), chosen by the extension you type.

How to reach it

Pick Export visible range… in the overflow menu, or press CtrlE.

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 — negative ages ending at 0 while streaming, offsets from the trigger edge while an event is held — so it is the x you read a value at on screen. abs_seconds is the source's own clock for the same sample, which is what lets two exports taken in different modes line up. 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.

MDF exists for handing a window to another tool, and its shape follows the contract that reader uses: one channel group, every channel record-interleaved, the master channel as the x axis and the unit in the channel metadata. So there the master is abs_seconds, named time — the clock that is the same in every display mode — and the display axis goes out beside it as an ordinary channel, time_relative. Both are seconds; each signal carries the source's own unit. That is also what ScryLab reads: channel name → signal name, master → x axis, unit → the signal's unit.

Example

A 2 s window at 10 kS/s over 3 traces writes 20001 rows and 5 columns (time, abs_seconds, 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)). The .mf3 is bigger — a block per channel plus a comment — 272 + comment + rows·record + 28 + channels·274 + 30 bytes, with record = 16 + 4·cols and channels = cols + 2 for the master and the relative axis. Read that one back with asammdf.MDF(path) or in ScryLab.