nxr-convert
Converts a Brainstorm protocol (MEG/EEG recordings, cortical surfaces, MRI volumes, head models, inverse kernels, source maps, fibres and connectomes) into an nxr datastore: a folder that the Cortical Flow desktop app opens.
Version 0.2.3, which writes database schema 49. Each dataset's dataset.sqlite carries the schema number as
PRAGMA user_version. The app opens only databases with the version it was built for, and the converter opens only its
own version and refuses any other. Use a converter release that matches your desktop app (0.2.x for Cortical Flow 0.2).
What it writes
<datastore>/
<dataset>/
dataset.sqlite the dataset's database: one row per subject, surface, recording, kernel, …
<subject>.nxr.zarr/ one Zarr v3 store per subject; the bytes (positions, faces, timeseries, kernels …)
The rows are written first, and every zarr.json is then rewritten from the rows, so the store describes itself. A
Brainstorm condition becomes a session of the subject. The protocol's default anatomy (@default_subject) becomes
the dataset's template subject, and Group_analysis becomes its group subject.
Install
Python 3.12 or newer. With uv:
uv tool install nxr-convert
or with pipx:
pipx install nxr-convert
Check the install:
nxr-convert --version # nxr-convert 0.2.3 (database schema 49)
The atlas commands also need the atlas extra (nibabel), plus Node.js and the nxr-compute Node binding
(NXR_COMPUTE). Install the extra with uv tool install "nxr-convert[atlas]".
The conversion commands below need neither.
Use with the Cortical Flow desktop app
The desktop app's Import runs this converter. It looks for one in this order:
NXR_CONVERT_CMD, an explicit command (for exampleuv run --project /path/to/nxr-convert nxr-convert);- a development checkout of the app's monorepo, run through
uv; nxr-convertonPATH;~/.local/bin/nxr-convert(nxr-convert.exeon Windows), whereuv tool installandpipx installput it — found even when the app was started from the Dock or Finder and did not inherit your shell'sPATH.
If none is found, the Import page shows a setup card. For an install elsewhere, set NXR_CONVERT_CMD to its full path.
Commands
Every command prints its progress as JSON lines on stdout, one object per event keyed by stage. The app parses this
output. A failure ends with a {"stage": "error", "message": …} line and exit status 1.
Datasets
nxr-convert dataset create <datastore> <name> [--source-tool brainstorm] [--source-protocol P] [--source-path S]
nxr-convert dataset delete <datastore> <name>
nxr-convert dataset recover <datastore>/<name> # roll back unfinished writes, finish deletions, rewrite the store
dataset create makes <datastore>/<name>/dataset.sqlite from the schema. It also creates the datastore folder if
it does not exist yet.
Reading a protocol
nxr-convert list <protocol> # its subjects and conditions, as JSON
nxr-convert scan <protocol> [--prefer protocol.mat|walk] [--out view.json] [--summary]
Converting
# one whole subject as one composition: every session, MRI volumes, source maps, fibres, connectomes
nxr-convert subject <protocol> --subject <name> --dataset <datastore>/<dataset>
# one condition as a session of a subject (the subject is created if it is absent)
nxr-convert convert <protocol> --subject <name> --condition <condition> --dataset <datastore>/<dataset> \
[--surface tess_*.mat] [--extra-surface tess_*.mat …] [--recording data_*.mat] [--channel-file F] \
[--no-gain] [--all-surfaces] [--include-imported] [--no-raw]
# the protocol's default anatomy as the TEMPLATE subject, and its group results as the GROUP subject
nxr-convert template <protocol> --dataset <datastore>/<dataset> [--surface tess_*.mat …]
nxr-convert group <protocol> --dataset <datastore>/<dataset>
<protocol> is the Brainstorm protocol folder, the one that holds anat/ and data/.
Adding to or removing from a subject
nxr-convert surface --dataset D --subject S --file tess_*.mat [tess_*.mat …] [--bst-root <protocol>]
nxr-convert mri --dataset D --subject S --anat <protocol>/anat/<subject> [--only NAME …]
nxr-convert inverse --dataset D --subject S --file results_*KERNEL*.mat --session C --bst-root <protocol> \
[--channels-id ID] [--surface-id ID] [--forward-id ID] [--name N] [--channel-file F]
nxr-convert remove --dataset D --subject S [--node <store path>] # the subject, or one node of it
The atlas (optional)
nxr-convert atlas default-subject <datastore>/<dataset> --templates <FreeSurfer subjects dir> […]
nxr-convert atlas build <datastore>/<dataset> --subject S [--replace] [--kernels …] […]
nxr-convert atlas reduce <datastore>/<dataset> [--from <datastore>/<other dataset> …] [--kernels …] # members of other datasets too
nxr-convert atlas info <datastore>/<dataset>
--kernels chooses the inverse kernels, in build and in reduce: comma tokens, tokens of one kind OR and kinds AND —
all · constrained | free · latest (per recording, method and orientation, the newest Brainstorm stamp) · a kernel's
method (MN_MEG), stamp (261005_2149), name, or a glob over its name. dSPM-unscaled_MEG,constrained,latest is one kernel
a recording. The group atlas sums one kernel per member recording, method and orientation: a member left with two (two
inverse solutions of one method) is refused, never pooled. Stamps are per subject (when Brainstorm made the kernel), so
across subjects choose by latest or a glob, not by one stamp.
Run nxr-convert <command> --help for every flag.
One writer per dataset
Each command that writes a dataset first takes its writer lock, <datastore>/<dataset>/.writer.lock. The lock is a
small JSON file (pid, host, program, started_utc) created atomically. If another live process holds the lock
(the desktop app, or a second conversion), the command is refused, and the error names the holder. A lock left by a
process that has died on the same machine is taken over. A lock held by another host is never broken; remove it by hand
if that host is gone. When the desktop app runs the converter during its own import, it already holds the lock and
passes it on through NXR_WRITER_LOCK_HELD. The lock is advisory, so do not edit a dataset by other means while a
conversion runs.
Development
uv sync
uv run pytest -q
Tests that need a real Brainstorm protocol skip unless NXR_TEST_PROTOCOL points at one (Brainstorm's
TutorialAuditory).
This repository is a published snapshot. The converter is developed inside the Cortical Flow monorepo, and its
database schema (src/nxr_convert/model.sql) is a copy of the app's schema.
License
MIT. See LICENSE.
Metadata
Release files for nxr-convert 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nxr_convert-0.2.3.tar.gz | 183.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nxr_convert-0.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 395.7 kB
Release files / nxr_convert-0.2.3.tar.gz
| Download URL | nxr_convert-0.2.3.tar.gz |
|---|---|
| Size | 183.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c68507c5ead00f4cf4f176cc6709365d252de05088fe7b509cff8039b64288ea
|
|
BLAKE2b-256 checksum How to use checksums |
dc9868caf970c2ff30424e004512e252cba28ae69fc4dfd770598e36bf119c20
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / nxr_convert-0.2.3-py3-none-any.whl
| Download URL | nxr_convert-0.2.3-py3-none-any.whl |
|---|---|
| Size | 212.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
94d4865fe9f9521267e44081f4a977a59e52fa290c7e74470a57acda1c8cc663
|
|
BLAKE2b-256 checksum How to use checksums |
3b79b75fce58b1b537e0faf0012fc613378a112fe9f6be9d2855be90fe21049a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|