MEGFlow is a preprocessing pipeline for MEG (Magnetoencephalography) data, built on MNE-Python and Nextflow.
It supports containerized execution, staged workflows, quality-control reports, and corpus-scale processing for research environments where reproducibility and scalable execution are required.
Containerized environments through Docker and Singularity reduce runtime differences across computational setups and support cross-subject or cross-site studies.
MEGFlow uses Nextflow to schedule independent tasks concurrently and manage large preprocessing workloads.
The workflow is organized into configurable stages so users can run the full pipeline or stop at selected milestones.
MEGFlow includes automated steps that reduce repeated manual work:
- Bad-channel and bad-segment detection
- ICA (Independent Component Analysis) component detection and labeling
- MEG-MRI coregistration
The reporting tools summarize quality-control metrics for each processing stage and flag potential anomalies.
Configuration files expose dataset paths, preprocessing settings, workflow steps, and report options without requiring changes to pipeline code.
MEGFlow 1.0.0 has been tested with Nextflow 24.10.3, MNE-Python 1.8.0,
Python 3.10/3.11, and Java 17.
The distributed image also starts under Nextflow 26.04+. MEGFlow uses DSL2
but currently selects the compatible v1 syntax parser because the workflow
still contains dynamic Groovy constructs that are not accepted by the v2
parser. The Docker entrypoint sets NXF_SYNTAX_PARSER=v1 automatically. For a
direct source launch with Nextflow 26, export the same variable before running
the pipeline.
For basic use, we recommend at least 8 CPU cores, 32 GB RAM, and 100 GB of free disk space, in addition to space for the input data and generated results. For multi-dataset processing, 16 or more CPU cores, 64 GB RAM, and SSD storage are recommended.
The first Docker installation usually takes 20โ90 minutes, mainly depending on the Docker image download speed. Demo processing may take tens of minutes to several hours, depending on the data size, selected steps, hardware resources, and configured parallelism.
MEGFlow is officially distributed as a Docker container. We recommend using the containerized installation workflow whenever possible, because it provides the most reproducible environment and avoids most local dependency conflicts.
If Docker cannot be installed, the Docker daemon is unavailable, or the container image cannot be pulled in your network environment, you can try the local development installation workflow instead. The local workflow installs MEGFlow from source without relying on a container image. Use this option cautiously, because differences in system libraries, package versions, and local software environments may lead to behavior that differs from the containerized workflow.
The commands below automatically download the matching installer into the current writable directory and run it immediately. You do not need to clone the MEGFlow repository or download the installer separately.
The commands always download the current installer from the main branch.
MEGFLOW_VERSION selects only the cplmeg/megflow image tag passed to that
installer. The recommended value is latest; use a published version such as
1.0.0 when you need to pin the image.
Run the following command in a terminal:
MEGFLOW_VERSION=latest && curl -fL -o install_megflow_linux.sh "https://raw.githubusercontent.com/jgaolab/megflow/main/scripts/install/install_megflow_linux.sh" && bash install_megflow_linux.sh "${MEGFLOW_VERSION}"The optional second argument selects auto (default), docker, apptainer,
or singularity. For example, force Apptainer with:
MEGFLOW_VERSION=latest && curl -fL -o install_megflow_linux.sh "https://raw.githubusercontent.com/jgaolab/megflow/main/scripts/install/install_megflow_linux.sh" && bash install_megflow_linux.sh "${MEGFLOW_VERSION}" apptainerThe Apptainer/Singularity path does not use a Docker daemon. It downloads the
published OCI layers from Docker Hub and converts them into
./megflow_<version>.sif (or MEGFLOW_SIF_PATH).
Run the following command in Terminal:
MEGFLOW_VERSION=latest && curl -fL -o install_megflow_macos.sh "https://raw.githubusercontent.com/jgaolab/megflow/main/scripts/install/install_megflow_macos.sh" && bash install_megflow_macos.sh "${MEGFLOW_VERSION}"Open Windows PowerShell, or open a PowerShell tab in Windows Terminal,
and paste the complete command below. Do not run it in Command Prompt
(cmd.exe) or Git Bash because it uses PowerShell syntax.
$MEGFLOW_VERSION = "latest"; $ErrorActionPreference = "Stop"; Invoke-WebRequest -Uri "https://raw.githubusercontent.com/jgaolab/megflow/main/scripts/install/install_megflow_windows.ps1" -OutFile "install_megflow_windows.ps1"; powershell -ExecutionPolicy Bypass -File .\install_megflow_windows.ps1 -ImageTag $MEGFLOW_VERSIONTo install a specific published image while still using the current installer,
set MEGFLOW_VERSION to that image tag:
MEGFLOW_VERSION=1.0.0 && curl -fL -o install_megflow_linux.sh "https://raw.githubusercontent.com/jgaolab/megflow/main/scripts/install/install_megflow_linux.sh" && bash install_megflow_linux.sh "${MEGFLOW_VERSION}"The commands above already download the installer automatically. Use these direct links only if you want to inspect a script first or save it for later manual execution:
Linux installer, macOS installer, and Windows installer.
For more details, see scripts/install/README.md.
Important: This is a source installation. The installer automatically clones or updates the GitHub source under
~/.megflow-dev/src/megflowby default. You do not need to clone the repository first or run from its root; download and execute the installer from any writable directory. Git and access to GitHub are required.
This workflow installs or reuses Conda, Nextflow, FreeSurfer, and MEGFlow source dependencies in a local installation directory.
curl -fL -o install_megflow_dev_linux.sh https://raw.githubusercontent.com/jgaolab/megflow/main/scripts/install-dev/install_megflow_dev_linux.sh && bash install_megflow_dev_linux.shAfter downloading it, rerun bash install_megflow_dev_linux.sh with options
such as --install-dir /data/megflow-dev or --no-freesurfer when needed.
After installation, load the generated environment:
source <install-dir>/env.shFor more details, see scripts/install-dev/README.md.
If you prefer to install manually, install Docker following the Docker official documentation. Browse the MEGFlow images and available version tags on Docker Hub, then pull the selected image directly:
MEGFLOW_VERSION=1.0.0 && docker pull "cplmeg/megflow:${MEGFLOW_VERSION}"docker run --rm -it cplmeg/megflow:<version> [megflow_options]Choose a public script by goal. The relative commands below assume the current
directory is the repository root. Launchers that use bundled configuration or
pipeline files resolve the repository root themselves; from another directory,
use an absolute script path and absolute paths for inputs such as --config.
Each script offers --help plus --dry-run where it launches an external
runtime.
| Goal | Public script |
|---|---|
| Process one dataset with the official Docker entrypoint | single-dataset Docker run |
| Process one dataset from a SIF with Apptainer or SingularityCE | single-dataset SIF run |
| Process every immediate dataset directory with Docker corpus mode | Docker corpus run |
| Run a configured corpus with host Nextflow | source corpus run |
| Open the Streamlit viewer for existing output | interactive report viewer |
Docker-backed launchers default to cplmeg/megflow:1.0.0. Use their
--image option only when deliberately selecting another published tag.
For a first single-dataset run, provide host paths for the input and output:
bash examples/run_scripts/single_dataset_docker.sh \
--input /data/meg_dataset \
--output /data/megflow_output \
--resumeFor an installed Apptainer or SingularityCE runtime, use the same input and output paths with a local SIF:
bash examples/run_scripts/single_dataset_sif.sh \
--input /data/meg_dataset \
--output /data/megflow_output \
--sif /data/megflow_1.0.0.sif \
--resumeThe complete run-script guide covers every option, expected output, and troubleshooting guidance.
The file nextflow/megflow.nf is controlled by params.megflow.defaults.steps plus optional dataset- or recording-level steps overrides in nextflow.config. The default is meg_all. The Docker entrypoint also accepts --steps and writes the corresponding params.megflow runtime override.
Primary steps |
What it does |
|---|---|
meg_all |
Default. Full MEG processing (import โ NMDQ score when megqc.enabled = true [default] โ basic preprocessing โ artifacts โ ICA โ epochs โ covariance โ coregistration โ forward โ source) using the existing fs_subjects_dir; does not run the T1/FreeSurfer/DeepPrep structural pipeline. |
all |
Run structural imaging (T1 import, recon, BEM; or Pseudo-MRI fallback when configured) and the full MEG chain in one go. |
anatomy |
Structural imaging only (no MEG). |
meg_artifacts |
MEG up to artifact detection (after basic preprocessing), then the static HTML QC report. |
meg_ica |
Through ICA (fit, label, apply), then report. |
meg_epochs |
Through epoching, then report. |
report |
Regenerate the static HTML report only (scans existing preproc_dir; no MEG or MRI processes). |
Aliases (same effect as the long name): meg โ meg_all, artifacts โ meg_artifacts, ica โ meg_ica, epochs โ meg_epochs.
Optional modifiers (comma-separated, e.g. --steps 'meg_epochs,skip_ica'; first token is the mode above):
| Modifier | When it is valid | Effect |
|---|---|---|
skip_ica |
Only with meg_epochs |
Skips ICA; loads the detected bad-channel and bad-segment sidecars into *_preproc-raw before building epochs. Not available for all / meg_all (downstream forward/source expect ICA-clean raw). |
with_anatomy |
meg_artifacts, meg_ica, or meg_epochs (not meg_all) |
Runs the structural and selected MEG branches in the same workflow. They may execute concurrently; downstream steps wait for anatomy only when required. |
Note: do_fs, do_only_anatomy, and top-level params.steps are no longer used by the Nextflow workflow. Put steps under params.megflow.defaults, a dataset profile, or a recording profile.
ICA per-component explained variance is optional and disabled by default:
set compute_explained_variance = true inside the nested defaults { ica { ... } }
block when you want EVAR values in ICA
figure filenames and report captions. When disabled, ICA fitting, labeling,
interactive review, and static reports still work; EVAR-dependent rule checks
are skipped.
The table above uses basic preprocessing for the first MEG-only signal steps (after import). They are defined in params.megflow.defaults.preproc; the repository default in nextflow/nextflow.config is:
- Band-pass filter (1โ100 Hz, IIR Butterworth)
- Notch filter (50 Hz and 100 Hz)
- Resample (250 Hz sampling rate)
Optional Maxwell / tSSS for MEGIN/Elekta data is configured as an OSL
maxwell_filter stage; a positive st_duration enables tSSS. Use the
three-level nextflow_maxwell_tsss_example.config
and the configuration reference
for calibration, cross-talk, ordering, bad-channel, and dataset/recording
override requirements. Maxwell/tSSS remains disabled in the shared defaults.
For CTF runs, if a matching *_headshape.pos is present next to the raw
file, digitization from the headshape is merged into the preprocessed FIF
after those steps.
For corpus runs with mixed line-noise frequencies, keep the default preprocessing shared and override only the relevant dataset profile:
params {
megflow {
datasets {
US_60Hz_Dataset {
preproc {
steps = [
[filter: [l_freq: 1.0, h_freq: 100.0, method: "iir", iir_params: [order: 5, ftype: "butter"]]],
[notch_filter: [freqs: "60"]],
[resample: [sfreq: 250]]
]
}
}
}
}
}NormMEG-QC has its own lightweight preprocessing setting,
params.megflow.defaults.megqc.preproc, so scoring stays aligned with the
configured reference space. The NormMEG-QC band-pass filter and sampling rate
are fixed at 1-100 Hz and 250 Hz for reference alignment; do not change those
values or the NMDQ score will no longer be comparable to the normative
reference. The scorer carries the same sequence internally, so an omitted or
empty megqc.preproc list still uses the reference defaults. Use
megqc.meg_vendor = "auto" by default so each recording is matched to the
appropriate reference device family. Vendor values are case-insensitive; the
examples use lowercase for consistency. If a corpus contains datasets whose
vendor is known and should be fixed explicitly, set it in the dataset profile:
params {
megflow {
datasets {
CTF_Dataset {
megqc {
meg_vendor = "ctf"
}
}
OPM_Artifacts {
megqc {
meg_vendor = "opm"
}
}
}
}
}NormMEG-QC parallelism is controlled by Nextflow resources, not a separate
megqc_n_jobs config value. The score_meg_quality process passes task.cpus
to the scorer; tune it with the global process.cpus setting or a process
override:
process {
withName: score_meg_quality {
cpus = 4
}
}To use the NMDQ score as a quality gate, raise megqc.min_score. Recordings below
that score are kept in the report but skipped for downstream MEG processing:
params {
megflow {
defaults {
megqc {
enabled = true
min_score = 70.0 // processing gate
alarm_score = 70.0 // report warning only
}
}
}
}Artifact review plots can use artifacts.meg_vendor: auto; MEGFlow will
infer the plotting vendor from channel names or raw metadata for each dataset.
DeepReject artifact detection is configured inside artifacts.deepreject and
is enabled by default in the bundled configs. BadChnNet first combines five-fold
predictions to identify bad channels. Those channels are then masked before
BadSegNet combines five-fold window probabilities and creates
BAD_deepreject intervals. MEGFlow merges these results with the other enabled
detectors, writes detector provenance to *_bad_channels_description.json, and
writes detailed inference provenance to deepreject_summary.json. The Docker
image includes the Torch runtime and bundled model weights; non-Docker local
environments must provide PyTorch. See the
DeepReject reference
for thresholds, modes, formulas, and output interpretation.
DeepReject applies the following model-only input recipe by default; the main workflow FIF is not modified:
params {
megflow {
defaults {
artifacts {
deepreject {
preproc = [
[filter: [l_freq: 1.0, h_freq: 100.0, method: "iir", iir_params: [order: 5, ftype: "butter"]]],
[notch_filter: [freqs: 50]],
[resample: [sfreq: 250]]
]
}
}
}
}
}Warning: A custom recipe or disabled preprocessing departs from the
model-validated default. Missing, null, or [] selects the built-in
recipe; a non-empty preproc list replaces it completely, while false or
off disables it. Upsampling runs normally but cannot recreate unavailable
source information; DeepReject records that and narrower source bandwidth as
limitations in deepreject_summary.json.
Examples (local Nextflow):
# Default: full MEG only, use existing FreeSurfer/DeepPrep subjects dir
nextflow run nextflow/megflow.nf \
-c nextflow/nextflow.config \
-resume
# Complete WAND + SMN4Lang + MEG-MASC example with per-dataset settings
bash examples/run_scripts/corpus_source.sh \
--config nextflow/nextflow_multi_dataset_demo.config
# To change the stage, edit the nested defaults block shown below.params {
megflow {
defaults {
steps = "all" // Or "anatomy" / "report" for those milestones.
}
}
}Set params.megflow.defaults.steps in your nextflow.config for a project default. For Docker runs, the entrypoint's --steps option writes this override into the runtime config.
MEGFlow relies on Nextflow -resume for normal task caching. Unchanged tasks
reuse the work cache, while input, script, or configuration changes invalidate
only the affected task chain.
Sidecar hashes are used for downstream invalidation. For example, editing bad-channel/bad-segment files changes the hash that ICA receives, so downstream tasks recompute even when the upstream artifact-detection task itself is cached. Editable sidecars are hashed from their published locations, so interactive report edits are preserved. Required published outputs also have task-local cache guards. If a QC, preprocessing, artifact, ICA, epoch, covariance, coregistration, forward, source, or anatomy result is deleted, a resumed run invalidates its producing task and restores that output while unrelated recordings remain cached. Static reports do not use resume cache and are regenerated on every completed or lenient run.
Every run writes preprocessed/logs/megflow_run_manifest.json. The static HTML report reads this manifest to draw the dataset-level Workflow diagram and to show the run mode, runtime, input data, paths, and only the parameters relevant to the selected stage.
The report also bundles a plain-text config snapshot at
static_html_report/data/nextflow.config.txt when one can be found. It checks
preprocessed/logs/, the dataset output root, and the manifest launch directory
for run_nextflow.config or nextflow.config. Docker runs copy their runtime
config to <output>/nextflow.config, so it is normally available there; custom
source launchers should retain their project config alongside the output when a
portable snapshot is required.
For --steps report, MEGFlow regenerates only the static report. If an earlier megflow_run_manifest.json exists, the report build uses it to keep the previous pipeline workflow in the diagram and marks the current run as report-only in the generated report bundle, but it restores the original preprocessed/logs/megflow_run_manifest.json afterward so the preprocessing provenance is not overwritten.
Subject pages also read the Nextflow trace.txt when available. Task Details
lists matched tasks in a collapsed table, while Task Failure Details appears
only when a failed or ignored task is detected and includes packaged
.command.err, .command.log, and .command.out excerpts. The amount of
task log content copied into the static report is controlled by
static_task_log_mode:
all-command-log(default): copy.command.err,.command.log, and.command.outfor failed or ignored tasks, and also copy.command.logfor successful tasks.failed: copy.command.err,.command.log, and.command.outonly for failed or ignored tasks when you want a smaller report package.none: do not copy.command*logs into the static report.
Set this in the active nextflow.config so source and Docker runs use the same
saved configuration:
params {
megflow {
defaults {
report {
static_task_log_mode = "all-command-log"
}
}
}
}Artifact Review in the static report packages one overview plot per subject by
default. The displayed window is controlled by
static_artifact_overview_duration (default: 200.0 seconds). Prefer setting
this value in the active Nextflow config file, for example
nextflow.config for source-code and Docker builds, so static report behavior stays reproducible with the saved
config snapshot.
For a directory that contains many independent MEG datasets, set
params.megflow.corpus_root and optionally narrow it with
dataset_include / dataset_exclude. MEGFlow treats each immediate child
directory as one dataset, isolates each dataset's outputs under
<output_dir>/datasets/<dataset_name>, and builds a corpus-level static report
that links back to each dataset report.
params {
megflow {
corpus_root = "/data/corpus"
dataset_include = ["WAND", "SMN4Lang", "MEG-MASC"]
datasets {
WAND {
fs_subjects_dir = "/data/corpus/WAND/smri"
meg_import {
task = ["visual"]
subject_id = "first:10"
}
megqc {
meg_vendor = "ctf"
}
epochs {
event_source = "find_events"
find_events {
stim_channel = "UPPT001"
}
}
}
SMN4Lang {
fs_subjects_dir = "/data/corpus/SMN4Lang_smri"
meg_import {
task = ["RDR"]
subject_id = "first:10"
}
megqc {
meg_vendor = "elekta"
}
epochs {
event_source = "event_file"
event_time_shift_sec = -10.6105
}
}
MEG_MASC {
dataset_format = "bids"
file_suffix = ".con"
meg_import {
session_id = ["0"]
task = ["0"]
subject_id = "first:10"
}
megqc {
meg_vendor = "kit"
}
artifacts {
meg_vendor = "kit"
deepreject {
mode = "lenient"
}
}
}
}
}
}The runnable nextflow/nextflow_multi_dataset_demo.config
expands this pattern into complete defaults, event and covariance definitions,
digitization, coregistration, source labels, and process concurrency limits for
all three datasets.
Outputs are organized as:
/output/datasets/<dataset_name>/static_html_report/index.htmlfor the existing dataset-level report./output/smri/<dataset_name>/for default dataset-isolated FreeSurfer/DeepPrep outputs when anatomy processing is enabled, or<fs_subjects_root>/<dataset_name>/whenparams.megflow.fs_subjects_rootis set./output/corpus_static_html_report/index.htmlfor the cross-dataset corpus dashboard./output/corpus_static_html_report/nextflow/for the corpus-level Nextflow report, timeline, trace, and driver log.
Use a milestone such as meg_artifacts or meg_ica for a quick first pass
across many public datasets, then resume selected datasets with a deeper step
when needed. Dataset-specific line-noise, vendor, epoch, covariance, and source
settings belong in the matching dataset profile. Task-specific settings belong
in that dataset's recordings profiles.
Dataset tuple channels and Nextflow's normal process parallelism handle
scheduling in one DAG. Local runs default to "auto" CPU, memory, and task
capacity, using the resources visible to the host or outer container. A fixed
workstation budget can be supplied in an additive config:
params {
megflow {
execution {
local_cpus = 16
local_memory = "48 GB"
local_max_tasks = 3
}
}
}local_max_tasks = N maps to the local executor queueSize. Actual
concurrency may be lower because CPU, memory, the workflow DAG, and per-process
maxForks limits all apply cumulatively. Keep maxForks for stages that need
an additional process-specific cap:
process {
withName: detect_artifacts {
maxForks = 2
}
}Native OMP, MKL, OpenBLAS, and NumExpr threads default to task.cpus for each
task. score_meg_quality and detect_artifacts use one native thread per
outer worker. Inside detect_artifacts, the DeepReject allocator keeps
fold_workers * cpu_threads <= task.cpus; detailed artifact-image workers are
also capped at task.cpus. Advanced users can override beforeScript globally
or in a process selector after validating the native library's threading
behavior.
The main config includes local, docker, slurm, singularity, lenient,
strict, and debug execution profiles. The docker profile containerizes the
complete source-launched workflow in the MEGFlow image; DeepPrep never launches
a nested container. Single-dataset runs write Nextflow observability
files under static_html_report/nextflow/; corpus runs use
corpus_static_html_report/nextflow/. MEGFlow launch wrappers pass the matching
nextflow/nextflow.log path through Nextflow's top-level -log option. Slurm
partition, account, QoS, work directory, queue size, and SIF settings are read
from MEGFLOW_SLURM_*, MEGFLOW_SIF, and MEGFLOW_SINGULARITY_* environment
variables. Source-launched Docker runs use MEGFLOW_DOCKER_IMAGE and
MEGFLOW_DOCKER_RUN_OPTIONS; see the configuration documentation for the
complete list and FreeSurfer license mount example.
The image entrypoint is nextflow/run_for_docker.sh (installed in the container as /program/nextflow/run.sh). Step selection uses the same values as in the Pipeline steps table above.
- After the image name, pass
-s/--steps. The entrypoint writes this into the runtimeparams.megflowprofile. If you omit it, the workflow usesparams.megflow.defaults.stepsfrom the config. - Pass
--anat-method deepprepafter the image name to select the anatomy implementation for one run. Valid values arefreesurfer,deepprep, andpseudomri; omitting it preserves the configuredanatomy.method. - Modifiers that contain commas must be quoted for the shell, e.g.
--steps 'meg_epochs,skip_ica'. - Corpus mode uses
--corpus; in that mode-i/--inputpoints to a directory whose immediate children are datasets, and--fs_subjects_diris used as the base directory for per-dataset FreeSurfer outputs. Named profiles,dataset_include,dataset_exclude, and dataset-level module overrides from the mounted config are preserved. - You can instead set
steps = '...'inside the nestedparams { megflow { defaults { ... } } }block in the Nextflow file mounted at/program/nextflow/nextflow.config; a container--steps/-sargument overrides that for the run. -shere is the MEGFlow flag (input path is-i), not Dockerโs-i(interactive). Typical pattern:docker run ... cplmeg/megflow:<tag> -i /input -o /output ... --steps all.- The container entrypoint copies the mounted config to
<output>/.nextflow-launch/run_nextflow.config, applies command-line path overrides, runs Nextflow with that writable file, and copies it to<output>/nextflow.configfor provenance and static-report packaging. - The Docker entrypoint starts as root only long enough to prepare mounted output permissions, then drops to the host UID/GID inferred from
/input; report-only runs that only mount/outputinfer ownership from/output.
Docker output ownership
You do not need to add Docker's --user flag or pre-create the output directory. If the host output path does not exist, Docker may create it as root:root before the container starts; MEGFlow fixes that at startup, then runs the pipeline as the host user inferred from /input. For interactive report runs such as docker run ... -v /data/preprocessed:/output cplmeg/megflow:<version> -r, ownership is inferred from /output. Outputs should therefore be writable by the submitting user, not owned by root.
Pre-create every other writable bind-mount source as the submitting user,
especially the structural directory used by -v /data/smri:/smri. Docker may
otherwise create a missing host path as root:root, leaving /smri unwritable
after MEGFlow drops privileges. Before anatomy or source processing, run
mkdir -p /data/smri and confirm test -w /data/smri succeeds.
Nextflow's docker.runOptions = '-u $(id -u):$(id -g)' syntax is valid when a
host Nextflow process launches a separate Docker container for each task. It is
not used by MEGFlow's distributed image, because Nextflow already runs inside
that outer container; enabling it there would require unsupported nested Docker.
If neither /input nor /output is owned by the user who should own generated files, pass the desired IDs explicitly:
docker run --rm -it \
-e LOCAL_UID="$(id -u)" -e LOCAL_GID="$(id -g)" \
-v /data/bids:/input -v /data/out:/output \
cplmeg/megflow:<version> \
-i /input -o /outputExamples:
# Full MEG only (explicit; same as default meg_all when config unchanged)
docker run --rm -it \
-v /data/bids:/input -v /data/out:/output -v /data/smri:/smri \
-v /data/license.txt:/fs_license.txt \
cplmeg/megflow:1.0.0 \
-i /input -o /output \
--fs_license_file /fs_license.txt --fs_subjects_dir /smri \
--steps meg_all
# Structural MRI + full MEG in one container run
docker run --rm -it \
-v /data/bids:/input -v /data/out:/output -v /data/smri:/smri \
-v /data/license.txt:/fs_license.txt \
cplmeg/megflow:1.0.0 \
-i /input -o /output \
--fs_license_file /fs_license.txt --fs_subjects_dir /smri \
--steps all
# Static HTML report only (existing preproc under preproc_dir)
docker run --rm -it \
-v /data/bids:/input -v /data/out:/output -v /data/smri:/smri \
cplmeg/megflow:1.0.0 \
-i /input -o /output --fs_subjects_dir /smri \
--steps reportThe Linux installer creates a local SIF that can run the same MEGFlow entrypoint. Bind host directories to the container paths used in the command:
mkdir -p /data/out
apptainer run --cleanenv \
--bind /data/bids:/input \
--bind /data/out:/output \
./megflow_1.0.0.sif \
-i /input -o /output \
--steps meg_ica --resumeUse singularity run in place of apptainer run on SingularityCE systems.
Add structural MRI, FreeSurfer license, and custom-config binds when those paths
are needed, for example:
apptainer run --cleanenv \
--bind /data/bids:/input \
--bind /data/out:/output \
--bind /data/smri:/smri \
--bind /data/license.txt:/fs_license.txt:ro \
--bind /data/megflow/nextflow.config:/program/nextflow/nextflow.config:ro \
./megflow_1.0.0.sif \
-i /input -o /output \
--fs_license_file /fs_license.txt \
--fs_subjects_dir /smri \
--steps all --resumeSIF root filesystems remain read-only. MEGFlow writes its generated runtime
configuration and Nextflow state beneath the bound /output directory.
| Option | Description |
|---|---|
-c, --config |
Specify the Nextflow config file (default: nextflow.config) |
-i, --input |
Specify the input directory |
-o, --output |
Specify the output directory (including report results) |
-s, --steps |
Sets the runtime params.megflow steps value (e.g. all, meg_all, anatomy, report). With Docker, pass this after the image name; see Using pipeline steps with Docker. Same semantics as Pipeline steps. |
--anat-method |
Sets the runtime anatomy method to freesurfer, deepprep, or pseudomri. Single-dataset mode overrides docker_input; corpus mode changes the shared default while preserving explicit named-dataset methods. |
-r, --view-report |
Run Streamlit to view the report (does not run Nextflow) |
--corpus |
Treat the input directory as a collection of datasets, preserve matching named dataset profiles, run each selected child through the native dataset tuple DAG, and generate a corpus-level static report |
--fs_license_file |
Specify the FreeSurfer license file path |
--fs_subjects_dir |
Specify the FreeSurfer SUBJECTS_DIR containing processed T1 results |
--t1_dir |
Specify the T1 image directory |
--resume |
Resume the previous run (Nextflow option) |
Other processing and report policy is configured in params.megflow, not
exposed as Docker entrypoint flags. This includes anatomy.t1_input_type,
anatomy.t1_dicom_series_glob,
report.static_task_log_mode, and
report.static_artifact_overview_duration. Put shared values under
params.megflow.defaults and dataset-specific values under the matching
params.megflow.datasets.<name> profile.
Example with input/output volumes and license files:
docker run --rm -it \
-v /data/datasets/SMN4Lang:/input \
-v /data/datasets/SMN4Lang/preprocessed:/output \
-v /data/datasets/SMN4Lang/smri:/smri \
-v /data/megflow/license.txt:/fs_license.txt \
-v /data/megflow/nextflow/nextflow.config:/program/nextflow/nextflow.config \
cplmeg/megflow:1.0.0 \
-i /input \
-o /output \
--fs_license_file /fs_license.txt \
--fs_subjects_dir /smri \
--resumeFor MEGFlow, the default steps is meg_all (MEG only, using existing fs_subjects_dir). To run structural MRI + full MEG together, use --steps all (or -s all) on the docker run ... command line, or set steps = 'all' in the mounted config's nested params { megflow { defaults { ... } } } block. See Using pipeline steps with Docker.
MEGFlow generates a portable static HTML quality-control report for each
processed dataset and a cross-dataset dashboard for corpus runs. The static
report is the primary review output and can be opened directly from
static_html_report/index.html or corpus_static_html_report/index.html.
An optional interactive Streamlit viewer supports closer inspection and manual editing of selected bad-channel, bad-segment, ICA, coregistration, and source review outputs.
For corpus-mode outputs, pass the output root with -o. The Streamlit viewer
detects datasets/<dataset_name>/ and adds a dataset selector in the sidebar;
each page then reads the selected dataset's preprocessed/ tree.
The command below starts the Streamlit interactive report viewer for existing
MEGFlow output. The -r option does not run Nextflow preprocessing and is
separate from opening the portable static HTML report. Map port 8501 to make
the interactive viewer available in a browser:
docker run --rm -it -p 8501:8501 \
-v /data/studies/LanguageStudy/megflow:/output \
cplmeg/megflow:1.0.0 -rAccess via browser:
http://<server_ip>:8501 (or http://localhost:8501 if running locally)
Contributions to MEGFlow are welcome. The public helpers below resolve the repository root once invoked. The shown relative invocations assume the current directory is the repository root; use an absolute script path, and absolute input or config paths, when invoking them from elsewhere.
Use a POSIX shell with Bash 3.2+ and Java 17 (up to 23). Source-mode workflow
development additionally needs Nextflow 24.10 or newer; Docker image work
needs a running Docker daemon; and documentation work needs the pinned packages
in requirements_doc.txt. Windows contributors can use WSL for Bash helpers,
while the native installer is validated separately in CI.
git clone git@github.com:jgaolab/megflow.git
cd megflow
nextflow infoInstall Nextflow using the official instructions,
then ensure it is on PATH. Use the source installation instructions in
scripts/install-dev/README.md when a local
MEGFlow environment is needed instead of the distributed image.
Run the fast routing gate used for push and pull-request checks from an activated MEGFlow environment:
export MEGFLOW_NEXTFLOW="$(command -v nextflow)"
bash scripts/validation/run_validation.sh routing-cirouting-ci runs static routing contracts, parses tracked Nextflow configs,
and executes a representative Nextflow 24.10.3 smoke matrix. routing adds
the exhaustive local routing, resume-deletion, failure, report, and
documentation-example matrices. scientific runs synthetic MNE/OSL filtering,
epochs, covariance, source-call, NormMEG-QC, DeepReject-input, MEGNet/ICA-label,
and report tests. all runs the complete local gates and builds documentation
when its dependencies are installed. Requested gates fail if dependencies are
missing, no tests are discovered, or any test is skipped.
GitHub Actions runs routing-ci, scientific, native Linux installer and
native macOS installer jobs, Windows parser/contracts on the Windows runner,
and the strict documentation build for every push and pull request. The
exhaustive routing matrix remains a local pre-release gate. Pinned lightweight
scientific dependencies are in requirements_validation.txt.
| Helper | Purpose and command | Prerequisites, output, and safety |
|---|---|---|
| build_megflow.sh | Build the local cplmeg/megflow:local image: bash scripts/development/build_megflow.sh --dry-run |
Docker is required outside dry-run; builds from megflow.Dockerfile and does not overwrite a release tag by default. |
| build_docs.sh | Build documentation: bash scripts/development/build_docs.sh --strict |
Python/Sphinx dependencies are required; writes HTML under docs/build/html by default. |
| docker2sif.sh | Convert an existing local image: bash scripts/development/docker2sif.sh --image cplmeg/megflow:local |
Apptainer or Singularity is required even for dry-run; Docker and the local-image check are required only for conversion. It neither pulls nor builds an image and refuses an existing output unless --force is explicit. |
All three helpers provide --help. Read their option descriptions before using
them on a shared workstation or cluster.
After changing the Dockerfile or packaged dependencies, inspect the assembled build command first and then run it when the local Docker daemon is available:
bash scripts/development/build_megflow.sh --dry-run
bash scripts/development/build_megflow.sh --tag localThe default output is the local development image cplmeg/megflow:local. Use
--image, --tag, --dockerfile, --platform, or --no-cache only when the
change requires them.
Build the HTML documentation with CI-equivalent warning handling:
bash scripts/development/build_docs.sh --strictThe default output is docs/build/html. --clean removes only the selected
documentation output directory before rebuilding; choose a custom --output
when retaining a separate preview is useful.
Preview or convert a development image that already exists on the local Docker daemon:
bash scripts/development/docker2sif.sh --image cplmeg/megflow:local --dry-run
bash scripts/development/docker2sif.sh --image cplmeg/megflow:localThe helper discovers Apptainer or Singularity before assembling either command,
so one of those runtimes is required for dry-run too. Docker availability and
the local-image check apply only to an actual conversion. The helper writes a
sanitized .sif filename unless --output is specified and does not build or
pull an image automatically.
Create a focused branch, run the relevant validation mode and strict documentation build, then commit and open a pull request. Include the command and output needed to reproduce any user-visible pipeline or documentation change. Keep unrelated local or site-specific launchers out of the change.
Please report bugs, unexpected behavior, or improvement suggestions through the GitHub Issues page.
When reporting a bug, please include:
- System Information: OS version, Docker version.
- Command Used: The exact command line you executed.
- Logs: The relevant part of the error log or traceback (please use code blocks).
- Description: A clear description of what you expected to happen versus what actually happened.