For agents#
This page is for coding agents (and people) who use modewise to analyse data. It lists how to
discover what modewise can do, the workflow, and the conventions that are easy to get wrong.
llms.txt at the site root indexes the documentation in markdown, and
llms-full.txt holds all of it in one file.
Discover operations instead of guessing#
Every pipeline step names an operation. Do not invent operation or parameter names: list them.
Python:
modewise.operations()returns each operation’s name, summary, inputs and outputs (port names and data kinds) andparams, a JSON Schema with types, descriptions, defaults and the required parameters.Shell:
modewise ops --jsonprints the same;modewise opsis a short human list.Docs: the operation reference is generated from the same data.
Unknown parameters are rejected, and missing ones take the defaults in the schema.
Workflow#
Describe the data in a dataset spec (datasets): file patterns with
{entity}fields, the format, and the sampling rate (a sidecar orsampling_rate_hz). Check it withmodewise inspect dataset.toml --loadbefore running anything.Write the pipeline in TOML or as a dict (pipelines). Parsing it checks every operation, parameter, reference and data kind, so a pipeline that loads will run.
Run it with
Pipeline.run_dataset(dataset, "results/")ormodewise run. Unchanged steps are reused from the results folder. One failing recording does not stop the others; readBatchRun.failed.Collect features across recordings with
Results.feature_table(features), or arrays withResults.stack. Values you derive yourself go intomodewise.FeatureTable(...).Test with
test_groups,test_pairedortest_correlation(statistics); usep_fwerorq_fdr, not the uncorrected p-values, when many features are tested.
A complete run#
import numpy as np
import h5py
import modewise
# A tiny dataset: eight subjects, two channels, 1.25 Hz.
rng = np.random.default_rng(0)
t = np.arange(400) / 1.25
for subject in ["01", "02", "03", "04", "05", "06", "07", "08"]:
rhythm = np.sin(2 * np.pi * 0.05 * t + rng.uniform(0, 6))
with h5py.File(f"sub-{subject}_task-rest_bold.h5", "w") as f:
f["timeseries"] = np.vstack([rhythm, rng.standard_normal(t.size)]) + 0.3 * rng.standard_normal((2, t.size))
dataset = modewise.Dataset.from_toml("""
root = "."
[[input]]
name = "bold"
pattern = "sub-{subject}_task-{task}_bold.h5"
format = "hdf5"
dataset = "timeseries"
sampling_rate_hz = 1.25
""")
print(dataset.recordings)
# Look up an operation's parameters before using it.
spectrum = next(op for op in modewise.operations() if op["name"] == "spectrum")
print(spectrum["summary"], sorted(spectrum["params"]["properties"]))
pipeline = modewise.Pipeline.from_dict({
"pipeline": {"name": "amplitude", "inputs": ["bold"]},
"step": [{"id": "psd", "op": "spectrum", "input": "bold"}],
})
batch = pipeline.run_dataset(dataset, "results", progress=False)
assert not batch.failed, batch.failed
table = batch.results.feature_table("amplitude", "psd", "band_amplitude",
bands={"slow4": (0.027, 0.073), "slow5": (0.01, 0.027)})
report = modewise.test_paired(table, ("slow4", "slow5"), n_permutations=1000, seed=0)
print(report.feature_names, report.t.round(1), report.p_permutation)
Conventions#
Arrays are channels × samples in; modes are mode × channel × sample; time–frequency power is channel × frequency × time; connectivity is window × component × channel × channel.
Modes go from low to high frequency. For EMD-family results mode 0 is the residual, and for the MODWT MRA it is the smooth.
Aligned or not:
Decomposition.aligned_across_channelssays whether mode k is the same band in every channel (MVMD, MEMD, MODWT MRA) or not (VMD, EMD, EEMD, CEEMDAN, whose per-channel frequencies are inchannel_centre_frequencies_hz, NaN where a channel has fewer modes). Do not compare mode k across channels when it is not aligned.Epochs need an explicit lag (
lag_s, the haemodynamic delay in fMRI, 0 for EEG), and are cut from a full-run result: decompose first, then epoch (epochs). Checkresolvablebefore using a slow mode in a short epoch.Large intermediates: set
keep = falseon steps whose outputs only feed later steps (for example modes before connectivity); they are then not written to the results folder.Seeds: methods that use noise (NA-MVMD, EEMD, CEEMDAN) and permutation tests take a
seed; set it for reproducible results.Every method states its sources and where references disagree; read the method page before explaining a result (EMD, wavelets, VLMD).
When something fails#
Errors name the problem: the step, the parameter, the file or the recording. A ValueError from
Pipeline.from_toml or Dataset.from_toml means the spec is invalid and nothing ran.
BatchRun.failed maps each failed recording to its error. In the shell, exit code 2 means some
recordings failed and 1 means invalid input.