Import Data from Python & MATLAB
ScryLab exposes a REST API at http://localhost:5678 that lets you import signals from Python, MATLAB, or any other environment — see the API reference for all parameters and error codes.
Prerequisite: Is the API reachable?
Make sure ScryLab is running and the API responds before sending data.
import requests
response = requests.get("http://localhost:5678/api/status")print(response.json())# {"status": "running", "port": 5678}response = webread('http://localhost:5678/api/status');disp(response.status) % runningcurl http://localhost:5678/api/status# {"status": "running", "port": 5678}Step 1: Get a data source ID
Every signal belongs to a data source. You need its ID before you can send data.
Option A — use an existing data source
import requests
response = requests.get("http://localhost:5678/api/sources")sources = response.json()["result"]
for source in sources: print(f"{source['name']}: {source['source_id']}")
# Pick the desired source ID from the list:source_id = sources[0]["source_id"]response = webread('http://localhost:5678/api/sources');sources = response.result;
for i = 1:length(sources) fprintf('%s: %s\n', sources(i).name, sources(i).source_id);end
% Pick the desired source ID from the list:source_id = sources(1).source_id;curl http://localhost:5678/api/sources | jq '.result[] | "\(.name): \(.source_id)"'Option B — create a new data source
import requests
response = requests.post( "http://localhost:5678/api/sources", json={"name": "My Measurements"})source_id = response.json()["result"]["source_id"]print(f"New data source: {source_id}")response = webwrite('http://localhost:5678/api/sources', ... struct('name', 'My Measurements'));source_id = response.result.source_id;fprintf('New data source: %s\n', source_id);SOURCE_ID=$(curl -s -X POST http://localhost:5678/api/sources \ -H "Content-Type: application/json" \ -d '{"name": "My Measurements"}' | jq -r '.result.source_id')echo "New data source: $SOURCE_ID"You can also create a new data source from the UI (see Import data sources).
Step 2: Send signals
ScryLab supports two transfer methods:
- JSON inline — data directly in the request body
- File reference — path to a
.npzor.matfile
Performance comparison (1M samples, float64)
| Method | Payload size | Parse time | Recommended for |
|---|---|---|---|
| JSON inline | ~16 MB | ~500 ms | < 50k samples |
| File reference | ~4–8 MB | ~20 ms | > 50k samples |
Method 1: JSON inline
Pass signal data directly in the request body as arrays.
If no x array is provided, ScryLab automatically generates an integer axis (0, 1, 2, …).
import numpy as npimport requests
BASE_URL = "http://localhost:5678"# source_id ← from Step 1
t = np.linspace(0, 1, 1000)y = np.sin(2 * np.pi * 5 * t)
response = requests.post( f"{BASE_URL}/api/signals/send", json={ "name": "Sine 5Hz", "y": y.tolist(), "x": t.tolist(), "y_unit": "V", "x_unit": "s", "target_source_id": source_id })
print(response.json())# {'status': 'ok', 'result': {'name': 'Sine 5Hz', 'sample_count': 1000, ...}}BASE_URL = 'http://localhost:5678';% source_id ← from Step 1
t = linspace(0, 1, 1000);y = sin(2*pi*5*t);
body = struct('name', 'Sine 5Hz', 'y', y, 'x', t, ... 'y_unit', 'V', 'x_unit', 's', ... 'target_source_id', source_id);response = webwrite([BASE_URL '/api/signals/send'], body);disp(response)curl -s -X POST http://localhost:5678/api/signals/send \ -H "Content-Type: application/json" \ -d "{ \"name\": \"Sine 5Hz\", \"y\": [0, 0.841, 0.909, 0.141, -0.756], \"x\": [0, 0.25, 0.5, 0.75, 1.0], \"y_unit\": \"V\", \"x_unit\": \"s\", \"target_source_id\": \"$SOURCE_ID\" }"Method 2: File reference
For large signals, save the data to a .npz or .mat file and send only the path. Arrays must be named y, x (and optionally z). Files that the Python client automatically places in ~/.cache/scrylab/transport/ are deleted after import. Paths outside that folder are left untouched.
import numpy as npimport requests
FILE_PATH = "/home/user/data/signal.npz" # ← adjust
# Prepare the file (arrays must be named y, x)t = np.linspace(0, 1, 1_000_000)y = np.sin(2 * np.pi * 5 * t)np.savez(FILE_PATH, y=y, x=t)
# Send only the path — not the contentsBASE_URL = "http://localhost:5678"# source_id ← from Step 1
response = requests.post( f"{BASE_URL}/api/signals/send", json={ "name": "Large Signal", "file": FILE_PATH, "y_unit": "V", "x_unit": "s", "target_source_id": source_id })print(response.json())FILE_PATH = '/home/user/data/signal.mat'; % ← adjust
% Prepare the file (variables must be named y, x)t = 0:1e-6:1;y = sin(2*pi*5*t);x = t;save(FILE_PATH, 'y', 'x');
% Send only the pathBASE_URL = 'http://localhost:5678';% source_id ← from Step 1
body = struct('name', 'Large Signal', ... 'file', FILE_PATH, ... 'y_unit', 'V', 'x_unit', 's', ... 'target_source_id', source_id);response = webwrite([BASE_URL '/api/signals/send'], body);disp(response)FILE_PATH="/home/user/data/signal.npz" # ← adjust
curl -s -X POST http://localhost:5678/api/signals/send \ -H "Content-Type: application/json" \ -d "{ \"name\": \"Large Signal\", \"file\": \"$FILE_PATH\", \"y_unit\": \"V\", \"x_unit\": \"s\", \"target_source_id\": \"$SOURCE_ID\" }"Linux Flatpak
The ScryLab Flatpak has --filesystem=home — paths under ~/ work. /tmp/ is not shared with the host (sandbox-private). Use ~/.cache/scrylab/transport/ as a temporary location for file references.
Waterfall and Spectrogram
By providing a z field, signals can be displayed with a third dimension.
Waterfall line (1D z-axis)
Not yet implemented
The 1D z-axis is not yet supported, as per-point color coding for line plots is still under development.
A 1D z array of the same length as x and y — each data point receives a color value.
import numpy as npimport requests
BASE_URL = "http://localhost:5678"# source_id ← from Step 1
t = np.linspace(0, 10, 500)y = np.sin(t)z = np.abs(y) # e.g. temperature along the curve
response = requests.post( f"{BASE_URL}/api/signals/send", json={ "name": "Colored Sine", "y": y.tolist(), "x": t.tolist(), "z": z.tolist(), "y_unit": "V", "x_unit": "s", "z_unit": "°C", "target_source_id": source_id })print(response.json())BASE_URL = 'http://localhost:5678';% source_id ← from Step 1
t = linspace(0, 10, 500);y = sin(t);z = abs(y);
body = struct('name', 'Colored Sine', 'y', y, 'x', t, 'z', z, ... 'y_unit', 'V', 'x_unit', 's', 'z_unit', '°C', ... 'target_source_id', source_id);response = webwrite([BASE_URL '/api/signals/send'], body);disp(response)Spectrogram (2D z-matrix)
A 2D matrix z of shape (M, N) with y as the frequency axis (length M) and x as the time axis (length N).
import numpy as npimport requests
BASE_URL = "http://localhost:5678"# source_id ← from Step 1
freqs = np.linspace(0, 1000, 128) # M = 128 frequency binstimes = np.linspace(0, 5, 256) # N = 256 time stepsz_matrix = np.random.rand(128, 256) # Shape: (len(y), len(x))
response = requests.post( f"{BASE_URL}/api/signals/send", json={ "name": "Spectrogram", "y": freqs.tolist(), "x": times.tolist(), "z": z_matrix.tolist(), "y_unit": "Hz", "x_unit": "s", "z_unit": "dB", "target_source_id": source_id })print(response.json())BASE_URL = 'http://localhost:5678';% source_id ← from Step 1
freqs = linspace(0, 1000, 128);times = linspace(0, 5, 256);z_matrix = rand(128, 256);
body = struct('name', 'Spectrogram', 'y', freqs, 'x', times, 'z', z_matrix, ... 'y_unit', 'Hz', 'x_unit', 's', 'z_unit', 'dB', ... 'target_source_id', source_id);response = webwrite([BASE_URL '/api/signals/send'], body);disp(response)