Matlab Prepare Signal Data
MathWorksOfficialCreated by MathWorks
- Skill
- Tool integration
- Data and AI
- BSD-2-Clause
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured approach to signal data preparation, guiding users through the lifecycle of cleaning raw signals, managing datastores, applying labels, and partitioning data for machine learning. It emphasizes using high-level Signal Processing Toolbox functions to ensure readability and maintainability, while offering clear heuristics for ordering conditioning steps like detrending, smoothing, and outlier removal. The skill is designed to help users move from raw data to a ready-to-train state for models like trainnet.
What it does
- Cleans signals by filling gaps, removing drift, denoising, and handling outliers.
- Synchronizes and resamples multi-channel data onto a uniform time base.
- Builds data pipelines using signalDatastore for efficient loading.
- Creates labeledSignalSet objects for structured labeling and Signal Labeler interoperability.
- Performs stratified splits and framing for long signal sequences.
- Shapes and prepares datastore outputs for machine learning workflows.
When to use it
- When you need to clean a single signal before analysis or training.
- When preparing a dataset of signals for machine learning with specific labeling requirements.
- When you need to align multiple signal channels or resample them to a uniform rate.
- When you need to partition signal data into training, validation, and test sets.
- When you need to frame long signals for windowed analysis or supervision.
Advantages
- Promotes readable, maintainable code by preferring high-level toolbox functions.
- Provides a logical, verified order for conditioning steps to prevent data corruption.
- Reduces manual effort by automating common tasks like label derivation from filenames.
- Ensures compatibility with Signal Labeler and deep learning training functions.
- Offers clear guidance on when to escalate to lower-level methods.
Usage examples
- “How do I remove a linear trend from my signal?”
- The agent will recommend using detrend(x, 1) and explain why explicit degree specification is preferred for code clarity.
- “I have a folder of signal files; how do I create a datastore and split them for training?”
- The agent will guide you through using signalDatastore to load the files, followed by splitlabels to perform a stratified split.
- “My signal has gaps; how should I fix them?”
- The agent will suggest using fillmissing for short gaps or fillgaps for longer gaps in oscillatory signals, depending on the signal characteristics.
- “How do I align two signals with different sampling rates?”
- The agent will recommend using the synchronize function to place both signals onto a shared time grid.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/matlab/matlab-prepare-signal-data/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip matlab-prepare-signal-data.zip -d .agents/skills
Documentation by MathWorks
Prepare Signal Data
Look in Signal Processing Toolbox first. The conditioning, labeling, splitting, framing, and partitioning helpers here live in Signal Processing Toolbox — not in Stats & ML Toolbox or generic-MATLAB string utilities.
The arc: condition a raw signal (clean it) -> load a folder into a
datastore -> label -> split / frame -> hand off to trainnet. Each
stage is a workflow file; this page routes you to the right one.
When to Use
Cleaning a single signal before analysis: fill gaps, remove drift, deoutlier, denoise, put it on a uniform time base, align multiple channels.
Loading / preparing signal data for ML training: datastores, labels from filenames or folders, stratified splits, framing, parallel processing.
Structured labeling:
labeledSignalSetfor Signal Labeler, all label types.
When NOT to Use
Raw
.wavaudio classification with Audio Toolbox available.audioDatastoreis the canonical path (this skill's custom-ReadFcnworkflow handles.wavonly when Audio Toolbox is absent — references/wf-custom-readfcn.md).Frequency-selective filter DESIGN (band isolation, notch, custom FIR/IIR) — see the
matlab-design-digital-filterskill. This skill's conditioning is about cleaning, not designing filters.Computing per-frame features (RMS, crest factor, spectral / bandwidth, time-frequency features) from an already-conditioned signal — see the
matlab-extract-signal-featuresskill. This skill'sframesig/framelblare for manual per-window labeling / supervision, not for deriving a feature table; thesignal*FeatureExtractorobjects window internally and emit the table.
Best practices
Deliverable is a runnable
.mscript the user can save, version, and re-run — not workspace state.Prefer the highest-level function that does the job.
detrend/smoothdata/fillmissing/resampleread cleanly and are easy for a non-expert to follow. Drop to a lower-level / more-configurable path (designfilt+filtfilt, a hand-built AR model, a named primitive) only when you need control the high-level call cannot give, or when the user asks. Readability first; escalate to low-level for necessity, not by default.The high-level call usually exposes the control you think you need. In particular
smoothdata(x, "sgolay", fl)takes the frame lengthflas an argument — it does NOT hide it — so prefer it over callingsgolayfiltdirectly. Reach forsgolayfiltonly for what the dispatcher genuinely lacks (derivative output viadn, or an unusual polynomial order).
0. Common reflexes
If your first instinct is one of these, the canonical replacement is one row away.
| Reflex | Canonical | Detail |
|---|---|---|
Hand-design a highpass/designfilt to remove a smooth drift | detrend(x, n) — escalate n = 1 -> 2 -> 3 before reaching for a filter; polynomial detrend has unity passband gain | references/fn-detrend.md |
Invent a gap-filler (regularizeNaNs, inpaintn — not real) | fillmissing (interp) for short gaps; fillgaps (SPT, AR) for long gaps in oscillatory signals | references/wf-repair-missing.md |
Hand-roll retime + shift + retime + concat to align channels | synchronize(A, B, ...) — one call to a shared grid | references/wf-align-channels.md |
Custom ReadFcn for a .csv | signalDatastore default reader + SignalVariableNames | references/fn-signaldatastore.md |
cvpartition for a datastore split | splitlabels + subset(ds, idx{k}) | references/fn-splitlabels.md |
regexp / extractBefore / fileparts for labels from filenames | filenames2labels(sds, Extract=...) | references/fn-filenames2labels.md |
regexp / nested fileparts for labels from subfolders | folders2labels(sds.Files) | references/fn-folders2labels.md |
Manual framing loop with (i-1)*hop+1 | framesig(x, fl, OverlapLength=...) | references/wf-frame-and-label.md |
Manual ROI-to-frame vote with containers.Map | framelbl(rois, ...) | references/wf-frame-and-label.md |
for loop load(file) to read in-file label variables | signalDatastore(folder, SignalVariableNames=["x","label"]) | references/fn-signaldatastore.md |
signalMask when you need Signal Labeler interop | labeledSignalSet with ROI labels (signalMask can't import) | references/fn-labeledsignalset.md |
signalLabeler(lss) (pass the set as an arg) | Launch bare signalLabeler (zero args), then Import -> From Workspace or From File | references/wf-label-and-export.md |
SPT-specialized functions exist — reach for them, don't reinvent.
fillgaps(AR gap fill),medfilt1/hampel(impulse handling),sgolayfilt/smoothdata(...,"sgolay")(feature-preserving smoothing) are in Signal Processing Toolbox.
1. Workflows
Each workflow file is the entry point and lists the functions it uses. Start here.
| Workflow | Use when | Reference |
|---|---|---|
| Repair missing samples | NaN gaps / dropouts to fill. | references/wf-repair-missing.md |
| Detrend, smooth, deoutlier | Drift, spikes, and/or broadband noise on one signal (smoothing/denoising lives here). | references/wf-detrend-smooth-deoutlier.md |
| Align multi-rate / offset channels | Several channels onto a shared time base. | references/wf-align-channels.md |
| Put one channel on a uniform rate | One channel -> uniform grid at a chosen rate: jittery timestamps to regularize, OR already uniform but the wrong rate to resample. | references/wf-uniform-rate.md |
| Wavelet denoising (escalation) | Non-stationary/multi-scale noise a tuned sgolayfilt can't remove; wdenoise (Wavelet TB). | references/wf-denoise.md |
| Envelope extraction | Amplitude outline (AM demod, peak hull) — not cleaning. | references/wf-envelope.md |
| Load + label + split | Folder of files -> datastore for training. | references/wf-load-and-split.md |
| Frame long signals + per-frame labels | Long signals, per-window supervision. | references/wf-frame-and-label.md |
| Label + export (all label types) | Structured labels (attribute/ROI/point/TF-ROI), export to Signal Labeler / DL. | references/wf-label-and-export.md |
| Parallel processing across a parpool | Per-signal work across workers. | references/wf-parallel-process.md |
| Custom ReadFcn (only when needed) | Format isn't .mat / .csv, or has a metadata prelude. | references/wf-custom-readfcn.md |
Hand-off to trainnet | Datastore ready; shape for trainnet / combine. | references/wf-handoff-to-dl.md |
Each workflow file names the
fn-reference pages for the functions it uses; there is no separate function index — enter through the workflow that matches your task, or the reflex table above.
2. Ordering when a signal needs several conditioning steps
The governing principle (this is the real rule): order the steps so an
earlier operation does not corrupt the input to a later one. Spikes bias
least-squares fits and get smeared by filters/resamplers; an un-removed trend
gets averaged into the signal by a smoother; most operations choke on NaN.
Reason from that for the signal in front of you — do not follow a fixed chain
blindly.
Default heuristic (a good starting order, not a universal law):
outliers -> detrend -> smooth, with fill and align placed by the principle above.
outliers -> detrend -> smooth is the verified core: remove spikes before a polynomial
detrend(a spike biases the fit) and before a smoother (a smoother spreads the spike across its window); detrend before smooth so the smoother isn't averaging across a trend.Fill
NaNbefore any step that can't handle missing data (detrend, filters, most smoothers).Align / resample: putting a signal on a new grid (
retime/synchronize) createsNaNat non-overlapping times, so fill after aligning. BUT if the signal has spikes, deoutlier before resampling —resample's anti-alias filter will smear an un-removed spike. So align-vs-outliers order depends on the signal; the principle decides, not a fixed sequence.
Not every signal needs every step — identify which apply, order them by the principle, and each workflow file has an off-ramp if your problem is actually a different family.
Copyright 2026 The MathWorks, Inc.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.0 KiB
- LICENSELicence file added by AutoGineer1.4 KiB
- SKILL.md9.5 KiB
- manifest.yaml650 B
- references/fn-countlabels.md2.1 KiB
- references/fn-detrend.md4.6 KiB
- references/fn-filenames2labels.md4.8 KiB
- references/fn-fillgaps.md3.3 KiB
- references/fn-fillmissing.md4.2 KiB
- references/fn-filloutliers.md5.0 KiB
- references/fn-folders2labels.md3.4 KiB
- references/fn-framelbl.md7.1 KiB
- references/fn-framesig.md4.1 KiB
- references/fn-hampel.md3.3 KiB
- references/fn-labeledsignalset.md9.1 KiB
- references/fn-labelspectrogramoptions.md4.6 KiB
- references/fn-medfilt1.md3.3 KiB
- references/fn-partition.md4.6 KiB
- references/fn-resample.md4.6 KiB
- references/fn-retime.md4.7 KiB
- references/fn-sgolayfilt.md3.5 KiB
- references/fn-signaldatastore.md11.9 KiB
- references/fn-signallabeldefinition.md5.9 KiB
- references/fn-signalmask-getmask.md8.6 KiB
- references/fn-smoothdata.md4.8 KiB
- references/fn-splitlabels.md5.3 KiB
- references/fn-subset.md3.9 KiB
- references/fn-synchronize.md4.7 KiB
- references/fn-wdenoise.md5.2 KiB
- references/wf-align-channels.md6.6 KiB
- references/wf-custom-readfcn.md5.0 KiB
- references/wf-denoise.md2.6 KiB
- references/wf-detrend-smooth-deoutlier.md6.6 KiB
- references/wf-envelope.md5.3 KiB
- references/wf-frame-and-label.md4.7 KiB
- references/wf-handoff-to-dl.md9.1 KiB
- references/wf-label-and-export.md8.7 KiB
- references/wf-load-and-split.md4.6 KiB
- references/wf-parallel-process.md4.8 KiB
- references/wf-repair-missing.md6.7 KiB
- references/wf-uniform-rate.md4.2 KiB
references/fn-signaldatastore.md
Function: signalDatastore
Used in: wf-load-and-split.md, wf-frame-and-label.md, wf-parallel-process.md, wf-custom-readfcn.md Toolbox: Signal Processing Toolbox
Constructor for a datastore over a folder of signal files. Default reader
covers .mat and .csv first-class — .wav requires audioDatastore or
a custom ReadFcn. Custom ReadFcn is reserved for genuinely non-tabular
formats.
Signature
sds = signalDatastore(location)
sds = signalDatastore(location, Name=Value, ...)
sds = signalDatastore(data) % in-memory form; use MemberNames + Memberslocation accepts:
A folder path (string or char). Files are returned alphabetically in
sds.Files.A single file path (string scalar or char vector).
Multiple file paths (string array or cell array of char vectors).
Wildcard
*in local paths (e.g."data/*.mat").A
matlab.io.datastore.FileSetobject (recommended for fast construction on large file sets) or amatlab.io.datastore.DsFileSetobject.Remote URLs (
hdfs://,http://,https://).
Name-value pairs / properties (full surface)
signalDatastore accepts two construction-only NV-pairs (IncludeSubfolders,
FileExtensions) plus any of its properties as NV-pairs (except Files,
which is set by location). Properties can also be set after construction.
File-location and reader controls
| NV-pair | Default | Purpose |
|---|---|---|
FileExtensions | .mat if any .mat files exist, else .csv | Filter the folder by extension. With the default reader, only .mat and .csv are valid; for other formats use ReadFcn. Errors at construction if neither .mat nor .csv files are present and no ReadFcn is set. Always set when the data folder also contains scripts or sub-folders. |
IncludeSubfolders | false | Recurse into sub-folders (true) or stop at top level. |
ReadFcn | built-in read | Custom reader function handle. Both 1-output data = readFcn(filename) and 2-output [data, info] = readFcn(filename) signatures are valid (see "Custom ReadFcn" below). Required for non-.mat / non-.csv formats. When set, SampleRateVariableName / SampleTimeVariableName / TimeValuesVariableName are not valid. |
AlternateFileSystemRoots | unset | String vector or cell array mapping equivalent root paths across machines (Windows ↔ Linux, local ↔ cluster). Required when the datastore is created on one machine and read on another with a different filesystem layout. |
Variable-naming controls (file data, default reader only)
| NV-pair | Default | Purpose |
|---|---|---|
SignalVariableNames | first variable in each file | Names of variables (.mat) or column headers (.csv) to read as signal data. Scalar string returns the array directly; vector returns a cell array. |
MemberNames | "Member1" .. "MemberN" | Names for in-memory data members (only when location is in-memory data, not file data). |
ReadOutputOrientation | "column" | Cell-array orientation when SignalVariableNames is a vector: "column" returns N×1, "row" returns 1×N. No effect with a single variable name. |
Time-information controls (file data, default reader only — mutually exclusive)
| NV-pair | Default | Purpose |
|---|---|---|
SampleRateVariableName | unset | Name of a per-file variable / column that holds a scalar sample rate. |
SampleTimeVariableName | unset | Name of a per-file variable / column that holds a scalar sample time. |
TimeValuesVariableName | unset | Name of a per-file variable / column that holds a time-values vector. |
Pick at most one of the three
*VariableNameproperties — they are mutually exclusive. None of them are valid whenReadFcnis set.
Read-output controls
| NV-pair | Default | Purpose |
|---|---|---|
ReadSize | 1 | Number of files (or members) returned per read call. When > 1, read returns a cell array. |
OutputEnvironment | "cpu" | "cpu" or "gpu". With "gpu", numeric read outputs are returned as gpuArray. Requires Parallel Computing Toolbox. Since R2024b. |
OutputDataType | "same" | Cast read output to "single", "double", or leave as "same". Pass either a scalar string (applied to all variables) or a string array of length N matching SignalVariableNames (per-variable). Length must be 1 or N — anything else errors. Each element must be one of "same", "single", "double". Since R2024b. |
In-memory data parameters
SampleRate (positive scalar / vector), SampleTime (positive scalar /
vector / duration), and TimeValues (vector / matrix / cell) work for
both in-memory and file data, attaching time information directly to the
datastore. Vector forms must have one element per signal.
Inspection-only properties
| Property | Set by | Purpose |
|---|---|---|
Files | location (read-only after construction) | Cell of resolved file paths in alphabetical order. Use sds.Files{k} to inspect the k-th file. |
Members | in-memory construction only | Cell array of in-memory member labels (paired with MemberNames). Not used for file-backed datastores. |
CSV is first-class
sds = signalDatastore(folder, ...
FileExtensions=".csv", ...
SignalVariableNames=["ch1","ch2"]);read(sds) returns a 1×N cell of column vectors per file (where N is the
number of named variables). For a single-column CSV, SignalVariableNames
is optional.
Headerless CSV. When the CSV has no header row, the default reader
autonames columns Var1, Var2, … — those are valid SignalVariableNames:
sds = signalDatastore(folder, FileExtensions=".csv", ...
SignalVariableNames=["Var1","Var2"]);2-output read works for the default reader, not just custom ReadFcn.
Use it when you want the per-file metadata that the datastore attaches
(e.g. info.FileName, info.SampleRate if SampleRateVariableName is
set):
[data, info] = read(sds);
% info.FileName -> path of the file just read
% info.SampleRate -> scalar Fs (when SampleRateVariableName is set)sds = signalDatastore(folder, ...
FileExtensions=".csv", ...
SignalVariableNames="x", ...
SampleRateVariableName="fs"); % fs column carries scalar Fs per fileIn-file labels — replace the load(file) loop
If the label is a variable inside each .mat file (e.g. x is the signal,
label is a categorical scalar), name both in SignalVariableNames.
The datastore returns {signal, label} per read — the manual
load(file) loop goes away entirely.
% Files contain variables: x (signal) and label (categorical scalar).
sds = signalDatastore(folder, ...
FileExtensions=".mat", ...
SignalVariableNames=["x", "label"]);
% read returns {signal, label} per file:
out = read(sds);
signalK = out{1};
labelK = out{2};
% Aggregate labels for splitlabels in one readall (lazy until then):
contents = readall(sds); % numFiles×1 cell of {x, label}
labelCells = cellfun(@(c) c{2}, contents, ...
UniformOutput=false); % cell of label scalars
labels = vertcat(labelCells{:}); % categorical column vectorAnti-pattern this replaces:
% Bad — manual load loop just to extract labels:
labels = strings(numel(sds.Files), 1);
for k = 1:numel(sds.Files)
s = load(sds.Files{k}, "label");
labels(k) = s.label;
endIf the only reason you're looping is to read a single in-file variable for
labels, list it in SignalVariableNames and let the datastore handle it.
Large signals — read the labels separately. If the signal is gigabytes
and the label is one scalar per file, readall(sds) with both variables
named pulls every signal into memory just to get the labels. Build a
second, label-only datastore and readall that one instead:
% Signal datastore — keeps the signal lazy:
sds = signalDatastore(folder, FileExtensions=".mat", ...
SignalVariableNames="x");
% Label-only datastore — same files, only the label variable:
labelSds = signalDatastore(folder, FileExtensions=".mat", ...
SignalVariableNames="label");
labelCells = readall(labelSds); % numFiles×1 cell of label scalars
labels = vertcat(labelCells{:}); % loads only the labelsBoth datastores walk folder in alphabetical order, so labels(k)
corresponds to sds.Files{k} — the index spaces line up for
splitlabels → subset.
Anti-pattern
Don't write a custom ReadFcn wrapping readtable(..., 'SelectedVariableNames', ...)
for tabular CSV. The default reader does this directly via SignalVariableNames.
% Bad — re-implements what the default reader already does:
sds = signalDatastore(folder, ReadFcn=@(f) ...
table2array(readtable(f, "SelectedVariableNames", ["ch1","ch2"])));
% Good — default reader, NV pair only:
sds = signalDatastore(folder, FileExtensions=".csv", ...
SignalVariableNames=["ch1","ch2"]);Before reaching for ReadFcn
Tabular .mat/.csv almost never needs a custom reader - the default reader
plus SignalVariableNames / SampleRateVariableName covers it. The full
decision tree (default reader vs NV-pair vs custom ReadFcn, and where
.wav / non-tabular formats go) is the workflow decision: see
wf-custom-readfcn.md.
Custom ReadFcn (only when needed)
For genuinely non-tabular formats — custom binary, metadata prelude, etc.
Two signatures are valid:
% 1-output — when the reader has nothing to add beyond the data:
function data = myReader(filename)
data = ...;
end
% 2-output — when you need to inject SampleRate or other per-file metadata:
function [data, info] = myReader(filename)
fid = fopen(filename, "r");
% ... read header, sample rate, signal ...
data = signalVector;
info.SampleRate = fs;
fclose(fid);
endUse the 2-output form only when the reader needs to surface per-file
metadata (e.g. info.SampleRate) to downstream consumers. Otherwise the
1-output form is sufficient.
Datastore appends info.FileName automatically; user-supplied values are
overwritten.
Anti-pattern — eager-load inside ReadFcn
Don't load(file) and discard most variables. At scale this wastes memory
proportional to total file size, not to the variable you actually need.
% Bad — loads everything, uses one variable:
function data = badReader(filename)
s = load(filename); % loads all variables
data = s.x; % ... but only x is used
end
% Good — named load:
function data = goodReader(filename)
s = load(filename, "x"); % loads only x
data = s.x;
end
% Better — matfile for lazy access:
function data = lazyReader(filename)
m = matfile(filename);
data = m.x;
endGotchas
Always set
FileExtensionswhen the data folder also contains scripts or sub-folders. Without it,signalDatastorewill try to ingest non-data files and fail at first read.SignalVariableNames(notVariableNames). The NV pair hasSignalin the name. Wrong name = silent fall-through to the default behavior.read()return shape depends onSignalVariableNamescount. One variable → returns the array directly. N variables → returns1×Ncell.Order matches
sds.Files. The k-th file's read corresponds tosds.Files{k}and (for filename labels)labels(k).ReadOutputOrientationdoesn't transpose your data on disk — it controls how the datastore emits already-oriented data. If your stored signal is row-shaped and your network expects column-shaped, set this NV pair instead of writing atransformto transpose.
See also
transform(sds, fn)— apply preprocessing per observation. Cell-wrap pattern:transform(sds, @(p){fn(p{:})})for multi-output reads.read(sds)/readall(sds)/hasdata(sds)— datastore consumption primitives (MATLAB; not Signal Toolbox).For the default-reader CSV path end-to-end, see wf-load-and-split.md step 1.
Copyright 2026 The MathWorks, Inc.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- MathWorks
- Publisher
- MathWorks (Official)
- Source
- matlab/matlab-agentic-toolkit · skills-catalog/signal-processing/matlab-prepare-signal-data · commit 2a7f215
- Licence
- BSD 2-Clause License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by MathWorks.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-prepare-signal-data.zip