Metadata-Version: 2.4
Name: ide4eeg
Version: 1.0
Summary: Integrated Development Environment for EEG
Author-email: Piotr Durka <durka@fuw.edu.pl>
Maintainer-email: Piotr Durka <durka@fuw.edu.pl>
License-Expression: GPL-3.0-or-later
Project-URL: Homepage, https://gitlab.com/fuw_software/ide4eeg
Project-URL: Repository, https://gitlab.com/fuw_software/ide4eeg
Project-URL: Bug Tracker, https://gitlab.com/fuw_software/ide4eeg/-/issues
Keywords: eeg,neuroscience,signal-processing,mne
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Environment :: X11 Applications :: Qt
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: scipy<2.0,>=1.13
Requires-Dist: numpy<3.0,>=2.0
Requires-Dist: matplotlib<4.0,>=3.8
Requires-Dist: tqdm>=4.68.2
Requires-Dist: Pillow
Requires-Dist: mne<2.0,>=1.7
Requires-Dist: nibabel
Requires-Dist: readmanager>=2.0.1
Requires-Dist: pandas
Requires-Dist: send2trash
Requires-Dist: certifi
Requires-Dist: joblib
Requires-Dist: threadpoolctl
Requires-Dist: python-picard
Requires-Dist: mne-icalabel
Requires-Dist: PySide6<7.0,>=6.6
Requires-Dist: py7zr; sys_platform == "win32"
Provides-Extra: iclabel
Requires-Dist: onnxruntime; extra == "iclabel"
Provides-Extra: video
Requires-Dist: opencv-python-headless; extra == "video"
Requires-Dist: imageio[pyav]; extra == "video"
Requires-Dist: av>=14.0; extra == "video"
Requires-Dist: insightface>=1.0; extra == "video"
Requires-Dist: onnxruntime; extra == "video"
Dynamic: license-file

# IDE4EEG
[![PyPI](https://img.shields.io/pypi/v/ide4eeg.svg)](https://pypi.org/project/ide4eeg/)
[![Python versions](https://img.shields.io/pypi/pyversions/ide4eeg.svg)](https://pypi.org/project/ide4eeg/)
[![License: GPL-3.0](https://img.shields.io/badge/License-GPL_v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Pipeline](https://gitlab.com/fuw_software/ide4eeg/badges/main/pipeline.svg)](https://gitlab.com/fuw_software/ide4eeg/-/pipelines)
[![Releases](https://img.shields.io/badge/releases-GitLab-fc6d26?logo=gitlab)](https://gitlab.com/fuw_software/ide4eeg/-/releases)
[![Windows installer](https://img.shields.io/badge/Windows-installer-0078d4)](https://gitlab.com/fuw_software/ide4eeg/-/releases/permalink/latest)
[![macOS .dmg](https://img.shields.io/badge/macOS-.dmg-000?logo=apple)](https://gitlab.com/fuw_software/ide4eeg/-/releases/permalink/latest)
[![User Manual](https://img.shields.io/badge/manual-PDF-fc6d26?logo=gitlab)](https://ide4eeg-32a4da.gitlab.io/manual.pdf)
[![HTML manual](https://img.shields.io/badge/manual-HTML-1f8ceb?logo=html5&logoColor=white)](https://ide4eeg-32a4da.gitlab.io)
[![Knowledge base](https://img.shields.io/badge/knowledge%20base-LLM--maintained-8A2BE2?logo=bookstack&logoColor=white)](docs/maintainer-wiki/)

User-friendly interactive pipeline for EEG analysis. From preprocessing (including gaze detection in video-EEG) to publication-ready plots and interactive 3-D visualizations of advanced results (including matching pursuit, dipole localisation and connectivity). 

Debugging and explainability: IDE4EEG visualizes incremental changes to the signal in each step of the pipeline.


## Install

### If you have Python 3.11+

```bash
pip install ide4eeg 
```

After install, GUI offers installation of video tools on first use; 
see [Installation](#installation) for prerequisites (Java) and edge-case platforms.

### Pythonless simplified (Windows / macOS)

| Variant | Download | Installed | Includes | Use if you... |
|---|---|---|---|---|
| **lite** | ~875 MB | ~1.8 GB | EEG core, GUI, Svarog / empi / ConnectiVIS (Java bundled) | Analyse EEG only |
| **full** | ~1.3 GB | ~2.7 GB | lite + facetag, gaze, synced video (OpenCV, PyTorch, InsightFace, L2CS-Net, mpv + ffmpeg bundled) | Run video-artifact detection |

Sizes measured on the macOS Apple Silicon 0.9 builds; Windows is comparable (full installs to ~3 GB).

[Click here for latest releases](https://gitlab.com/fuw_software/ide4eeg/-/releases/permalink/latest)

| Platform | Installer | Portable |
|---|---|---|
| Windows 10/11 (x64) | `Ide4eegSetup-{lite,full}.exe` — double-click to install | `ide4eeg-{lite,full}-<tag>.zip` — unzip + run |
| macOS 12+ (Apple Silicon) | `IDE4EEG-{lite,full}-<version>-arm64.dmg` — drag to /Applications | — |
| macOS 12+ (Intel) | `IDE4EEG-lite-<version>-x86_64.dmg` — drag to /Applications (**lite only**, see below) | — |

> **Why Intel Macs get lite only:** PyTorch's last x86_64 macOS wheel (`torch==2.2.2`) predates NumPy 2 and was compiled against the NumPy 1.x C ABI, while IDE4EEG requires `numpy>=2.0`. The two cannot coexist, so a full bundle would ship a torch whose NumPy bridge never initialises — taking out ICLabel and L2CS gaze while appearing to install fine. The Intel lite build bundles `onnxruntime`, so **ICA with ICLabel works**; the video stack is not bundled, so the facetag / gaze panels stay disabled. Intel users who need gaze detection should `pip install ide4eeg[video]` instead, where InsightFace head-pose gaze runs on onnxruntime — L2CS eye-gaze is unavailable on Intel macOS either way, for the same torch reason.

> **macOS first-launch — macOS blocks it once. Four clicks, no Terminal:**
> 1. Drag the app from the `.dmg` window to **Applications**, then eject the `.dmg`.
> 2. Double-click the app. macOS refuses to open it — click **Done**. *(This step is required: the button in step 3 only appears after a blocked attempt.)*
> 3. Open **System Settings → Privacy & Security**, scroll down to the message naming the app, click **Open Anyway** and confirm with your password or Touch ID.
> 4. Double-click the app again. It opens, and macOS will not ask again.
>
> Depending on your macOS version, step 2's refusal reads as one of these — all the same block, none of them a defect in the app:
> - *"…cannot be opened because Apple cannot check it for malicious software…"*
> - *"Launch error — See the py2app website for debugging launch issues"* → **not** an application crash, despite how it reads: the launcher was stopped before it could start Python, and py2app reports any startup failure with this one generic dialog.
> - *"…is damaged… Move to Trash"* → the app is **not** damaged.
>
> Why any of this happens: the app is ad-hoc signed but **not notarized** (no Apple Developer Program enrollment). Downloading the `.dmg` attaches macOS's quarantine flag to it, and mounting propagates it to all ~21 000 files inside; while it is set, macOS runs the app from a randomised read-only copy (*App Translocation*) and Gatekeeper stops it. The flag is what decides this, not where the app sits — it behaves identically from the mounted DMG, from `/Applications` and from the Desktop.
>
> <details><summary>Terminal shortcut (optional)</summary>
>
> Clearing the flag by hand does the same thing without the click-through. On the disk image, **before mounting it**, one command covers the whole bundle:
> ```
> xattr -d com.apple.quarantine ~/Downloads/IDE4EEG-lite-<version>-arm64.dmg
> ```
> (If it is already mounted, eject and mount again — the flag reaches the contents at mount time.) Or, on an app already copied out:
> ```
> xattr -dr com.apple.quarantine /Applications/IDE4EEG.app   # or IDE4EEG-nogaze.app (lite)
> ```
> </details>
>
> **Windows first-launch:** SmartScreen shows "Windows protected your PC". Click **More info → Run anyway**. (Code signing pending on a future release.)

## Features

- Qt6 graphical interface (PySide6) with interactive signal preview, MP Book Viewer, 3D source visualization and integrated SVAROG viewer
- EEG data formats: `.raw` (BrainTech), `.vhdr` (BrainVision), `.fif` (MNE), `.set` (EEGLAB), `.edf` (EDF/EDF+), `.bdf` (BDF/BDF+)
- Matching Pursuit in Gabor dictionaries, Wigner time-frequency energy maps, nonlinear signal filtering
- Connectivity analysis: 13 measures (DTF, PDC, Coherence, GCI, AEC, etc.) via MVAR models
- EEG profiles: FASP-based graphoelements (spindles, alpha, delta, K-complexes) visualized over time
- Source estimation: MMP macroatom dipoles, classical ERP dipole fit, MNE/dSPM/sLORETA/eLORETA distributed inverse, LCMV beamformer, MxNE sparse — discrete-source methods feed ConnectiVIS natively; distributed methods opt-in via `n_peaks`
- Video artifact detection: face recognition (InsightFace) + gaze estimation (InsightFace or L2CS-Net) to flag intervals where the subject is not looking at the screen
- Preprocessing: re-referencing, filtering, bad-channel detection and removal, ICA, algorithmic artifact rejection (peak-to-peak amplitude, slope, high-frequency/muscle, flat)
- Time-domain analysis: grand-average ERPs, cluster permutation tests (MNE-Python catalog wrappers)
- ERP data quality: `ERP quality stats` (effect size, single-trial AUC, window-free cluster mass) and `SME` (standardized measurement error), both per channel and condition
- Frequency-domain analysis: PSD via Welch or multitaper methods (MNE-Python catalog wrappers)
- Time-frequency analysis: TFR via Morlet / multitaper, ERD/S topographic maps (MNE-Python catalog wrappers)
- Config-free script export: GUI generates a standalone Python script with only non-default parameters
- Public API (`ide4eeg.api`): `run_file()` for programmatic pipeline execution, plus individual step wrappers
- Batch-friendly CLI driven by a single TOML config file

## Quick Start

```bash
python3 -m venv .venv && source .venv/bin/activate   # Linux / macOS
# .venv\Scripts\activate                              # Windows
pip install ide4eeg
ide4eeg                         # launch GUI — auto-prompts for video tools on first use
```

No config file is needed to start — the GUI provides sensible defaults and
lets you configure everything interactively. For CLI batch processing, save
a config from the GUI and run `ide4eeg --run path/to/config.toml`.

## Installation

### Prerequisites

**Python 3.11–3.14.** Development happens on 3.14; the release tests (Linux and Windows CI) run on 3.13. 3.11 and 3.12 are expected to work but not exercised. Python < 3.11 will not work: the config loader uses `tomllib` (added to the stdlib in 3.11). Python 3.15 is not supported yet: PySide6 has no release for it.

**Java 17 LTS** (**11 is the minimum**; required for Svarog, the integrated signal viewer). Svarog 4 compiles to class-file 55, so a Java 8 or 10 JVM cannot load it at all — it fails with `UnsupportedClassVersionError`. Java **13+** additionally enables AppCDS, which cuts roughly 380 ms off each Svarog / ConnectiVIS cold start by reusing a cached class archive. SVAROG (signal viewer / MP Book Viewer) and ConnectiVIS (3D dipole + connectivity viewer) are standalone Java applications, and SVAROG drives every interactive review surface: View Step Result (👁), Bad Channels review, ICA component review, Drop Segments review, MP Book Viewer, opening saved `.fif` / `.raw` files in the Output tab. The headless CLI (`ide4eeg --run config.toml`) is the one path that runs without Java.

```bash
# macOS
brew install openjdk@17

# Ubuntu / Debian
sudo apt install openjdk-17-jdk

# Windows / cross-platform
# Download from https://adoptium.net (Eclipse Temurin, free)
```

The Svarog and ConnectiVIS jars themselves are fetched on demand by the GUI's **Download recent** button (Config tab) — you don't need to install them manually, only the JVM to run them. Java 16+ needs `--add-opens` flags for SVAROG's Swing reflection; IDE4EEG adds these automatically. Java 21 LTS also works.

### From a checkout (development)

```bash
git clone https://gitlab.com/fuw_software/ide4eeg.git
cd ide4eeg
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt   # = pip install -e .[video]
ide4eeg                            # editable; edits to ide4eeg/*.py go live
```

### The `[video]` extra (headless / scripted / CI)

`pip install ide4eeg` always succeeds (lite). The video stack (face / gaze artifact tagging) is normally installed in-app from the Config tab the first time you use video features — the GUI auto-prompts with a streaming-log dialog and a Cancel button.

For **headless / scripted / CI setups** where the GUI's auto-prompt never fires, install everything up-front:

```bash
pip install ide4eeg[video]
python -m ide4eeg.install_runner --repair-opencv   # run once, after the above
```

The second line is not optional housekeeping. `insightface` requires the non-headless `opencv-python`, and a pip extra cannot say "install this package but not its OpenCV", so the extra always ends with two distributions owning the same `cv2/` — and the non-headless one wins. On Linux that build points `QT_QPA_PLATFORM_PLUGIN_PATH` at its own bundled Qt 5.15 plugins as soon as `cv2` is imported. The repair uninstalls every variant and reinstalls the single headless one; it is safe to re-run and exits 0 when there is nothing to do. The GUI's **Install missing** button does this for you automatically, and a batch run warns if it detects the state.

The extra bundles OpenCV, PyAV, imageio, InsightFace and onnxruntime. L2CS-Net (the default eye-gaze backend, ~500 MB — the CPU PyTorch build, which is all IDE4EEG's gaze inference uses; the installer requests the CPU wheel on every platform) is **always** installed via the GUI's **Download recent** button — PyPI bans direct VCS dependencies and L2CS lives at a GitHub URL.

### Known wheel gaps

`pip install ide4eeg[video]` (and `ide4eeg[iclabel]`) fails on one platform cell because `onnxruntime` doesn't ship wheels everywhere. `pip install ide4eeg` (lite) always works.

| Cell | Affected dep | Resolution |
|------|--------------|------------|
| Intel Mac + Python 3.14 | `onnxruntime` (no cp314 x86_64 wheel; 1.23.2 was the last release with Intel Mac wheels, for Python up to 3.13) | Use lite install. To get the video stack, either downgrade to Python 3.13 (cp313 wheels exist) or use the GUI's **Install all video tools** button on the Config tab — it pip-installs in-process with the same constraint, so you'll see the same error in a friendlier dialog. There's no workaround that produces working video on this cell with cp314 today; the recommendation is Python 3.13. ICA is affected too: the ICLabel selector needs `onnxruntime` or PyTorch, and neither has a wheel for this cell, so ICA uses the `find_bads` selector. |
| Apple Silicon + any | none | Both `pip install ide4eeg` and `pip install ide4eeg[video]` work directly. |
| Linux + any Python (any arch) | none | Same as Apple Silicon. Python 3.14 was blocked here until 2026-07-31 (`insightface` / `stringzilla` had no cp314 wheels and built from sdist); upstream now ships a pure-Python `insightface` wheel and cp314 wheels for `stringzilla` / `simsimd` on x86_64 and aarch64, so no compiler is needed. |
| Windows + any | none | Same. |

The in-app installer shows pip's actual output in a streaming log dialog with a Cancel button. Cell-blocked packages produce a labelled "X package(s) platform-blocked" status with copy-paste remediation text instead of an opaque pip wheel-resolution error.

### Optional: GPU acceleration for facetag

By default IDE4EEG uses ONNXRuntime's CPU provider, plus CoreML on Apple Silicon Macs (automatic — no config needed). For significant speedup on NVIDIA or DirectX 12 hardware, swap the stock `onnxruntime` package for a hardware-specific variant:

```bash
pip uninstall -y onnxruntime
pip install onnxruntime-gpu       # NVIDIA (Linux/Windows)
# or
pip install onnxruntime-directml  # any DX12 GPU on Windows 10+
# or
pip install onnxruntime-openvino  # Intel CPU/iGPU/VPU
```

Expected facetag speedup on face detection/recognition versus the CPU baseline:

| Hardware             | Provider  | Speedup |
| -------------------- | --------- | ------- |
| Apple Silicon Mac    | CoreML    |  3–8×   |
| Intel Mac            | CPU       |    1×   |
| Linux/Windows NVIDIA | CUDA      |  5–20×  |
| Windows DX12 GPU     | DirectML  |  3–10×  |
| CPU only             | CPU       |    1×   |

Requirements for the GPU variants: `onnxruntime-gpu` needs CUDA Toolkit + cuDNN matching the package version; `onnxruntime-directml` needs Windows 10+ with a DirectX 12 GPU. IDE4EEG code is unchanged — InsightFace's provider list automatically picks up whichever ExecutionProvider your installed ORT variant supports. Check the Run log at pipeline start for `InsightFace detection session using: ...` to verify which backend activated.

## Architecture

```
GUI or config.toml
    |
    v
 input/          -- load raw EEG data (metadata-only for GUI preview)
    |
    v
 preprocessing/  -- filter, re-reference, ICA, artifact rejection
    |
    v
 analysis/       -- time, frequency, and time-frequency analysis
    |
    v
 plots/          -- generate figures
    |
    v
 IDE4EEG_OUT_<filename>/      -- all results in one folder
```

## GUI

Launch with `ide4eeg` (or `python -m ide4eeg`).  Pass an optional path — `ide4eeg myconfig.toml` — to preload a saved pipeline config into the form.

The interface has seven tabs:

1. **Config** — tool paths (Svarog, 3D view / connectivis, empi, mpv video backend) with **Download recent** button for one-click install from GitLab plus Homebrew-assisted mpv install on macOS, parallel-jobs and overwrite toggles.
2. **Input** — input signal, video, output paths; signal info (auto-read from headers); example data with reproducible figures from published papers.
3. **Preprocess** — collapsible step rows with per-step **Save** checkboxes (strictly user-driven, default off; only the eye button force-flips them on). Two fixed signal-setup steps (Drop Channels, Montage) are configured on the Input tab. The reorderable cleaning steps — Trim, Reference, Resample, Detect Bad Channels, Filtering, MP Filter, ICA, Gaze, EEG Artifacts — default to this canonical order (Reference is default-early, right after Trim; MP Filter before ICA) and can be dragged (enable "Allow reordering"). MP Decomposition is available as a reorderable step too, but off by default. A fixed Segmentation-setup header always runs; postamble (always runs): Cut Segments, Drop Segments.
4. **Analysis** — IDE4EEG-native: EEG Profiles (FASP), MP-book viewers, Connectivity, Source estimation (MMP dipoles + classical ERP fit + MNE/dSPM/sLORETA/eLORETA + LCMV + MxNE). MNE-Python catalog wrappers grouped into six category panels: ERP, Spectra, Time-frequency, Spatial, Comparison, Source estimation. Each with a Run button that executes via the Run tab.
5. **Run** — pipeline execution with compact stage status, progress bar, real-time log, and Stop button.
6. **Output** — browse output folders, preview images/CSV/FIF files, open in MNE or SVAROG.
7. **Help** — embedded reference with scientific citations.

A persistent top bar (visible on Config through Analysis tabs) provides Segments (continuous / event-locked) and Viewer (SVAROG/MNE) selection.

## Where IDE4EEG stores files

Two top-level filesystem locations cover everything installed at runtime:

- **`~/.obci/`** — external binaries (Svarog jar, empi, mpv portable, ConnectiVIS jar) plus IDE4EEG-managed runtime data under `~/.obci/ide4eeg/`:
  - `~/.obci/ide4eeg/models/L2CSNet_gaze360.pkl` — L2CS-Net gaze checkpoint (~96 MB, downloaded on first L2CS use).
  - `~/.obci/ide4eeg/insightface/models/buffalo_l/` — InsightFace face-detection / identity models (~200 MB, downloaded by InsightFace on first use; redirected from upstream's `~/.insightface/` default).
  - `~/.obci/ide4eeg/logs/ide4eeg.log` — rotating diagnostic log (the same messages the app's log panel shows, timestamped; keeps 3 rotated files, ≤ ~8 MB). Attach it to a bug report.
- **`<venv>/lib/python3.X/site-packages/`** — pip-installed Python packages including the eight video-stack libraries (`cv2`, `av`, `imageio`, `insightface`, `onnxruntime`, `torch`, `torchvision`, `l2cs`). Footprint ~250 MB core; the PyTorch + L2CS gaze stack adds ~500 MB (IDE4EEG installs the CPU PyTorch wheel on every platform — it never uses a GPU torch build). *(For optional onnxruntime GPU acceleration of InsightFace — a separate subsystem — see "GPU acceleration for facetag" above.)*

Existing installs with files in legacy locations (`~/.insightface/`, `<package>/preprocessing/facetag/models/`) are migrated automatically to `~/.obci/ide4eeg/` on first launch via same-disk renames — no re-downloads required when migration succeeds. See [USER_MANUAL — Where IDE4EEG stores files](ide4eeg/USER_MANUAL.md#where-ide4eeg-stores-files) for the full table and uninstall instructions.

## Troubleshooting

| Problem | Solution |
|---------|----------|
| `ModuleNotFoundError: No module named 'tomllib'` | Python < 3.11 is not supported. Upgrade to Python 3.11 or later. |
| `ModuleNotFoundError` after install | Make sure the virtual environment is activated (`source .venv/bin/activate`). |
| L2CS-Net won't install | Use the **Download recent** button on the Config tab next to "L2CS-Net (gaze detection)" — it installs torch + l2cs + the Gaze360 weights in one shot (the canonical, tested install path). |
| `Failed building wheel for insightface / stringzilla` (Linux, Python 3.14) | Fixed upstream — `insightface` 1.0.1 is a pure-Python wheel and `stringzilla` / `simsimd` ship cp314 wheels, so nothing compiles. If you still see this, pip is resolving older pinned versions: upgrade pip and let it pick current ones (`pip install -U pip && pip install -U ide4eeg[video]`). Confirm with `pip install --dry-run --only-binary :all: insightface albumentations`, which must succeed. |
| "Where are my results?" | Output goes to `IDE4EEG_OUT_<filename>/` next to your input file (or under the directory set in output path). |
| Qt platform plugin "xcb" error (Linux) | Install `libxcb-cursor0`: `sudo apt install libxcb-cursor0` (Debian/Ubuntu) or `sudo dnf install xcb-util-cursor` (Fedora). |
| SVAROG doesn't open / "Java not found" | Install Java 17: `brew install openjdk@17` (macOS) or `sudo apt install openjdk-17-jdk` (Linux) or download from [adoptium.net](https://adoptium.net). |
| SVAROG crashes with `InaccessibleObjectException` | You are running Java 16+ without the required module-open flags. Update IDE4EEG — recent versions add these flags automatically. |
| SVAROG fails with `UnsupportedClassVersionError` (…`class file version 55.0`…) | Your Java is older than 11. Svarog 4 is compiled for Java 11; Java 8 and 10 cannot load it. Install Java 17 (see Prerequisites above) — IDE4EEG ≥ 0.9 refuses an older JVM up front instead of letting the launch fail. |
| `onnxruntime` install fails on Intel Mac with Python 3.14 | Stay on the lite install (`pip install ide4eeg`). Two features need `onnxruntime`: video-based gaze detection, and the ICLabel selector of ICA (without it, ICA uses the `find_bads` selector). To get both, switch to Python 3.13, where the wheel exists. |
| Numbers won't enter into a GUI field (typed `0,5` rejected, `5.5` works) | IDE4EEG uses `.` (period) as the decimal separator regardless of system locale — TOML and Python `float()` both require it. Use `0.5`. Frequency / amplitude / scale fields also reject the `-` key at typing time (negative values are never valid there). |
| Desktop build (installer / portable) hangs or crashes at an analysis step | Set **Parallel jobs = 1** on the Config tab. Standalone builds run everything that uses joblib / MNE workers (filtering, resampling, the MNE catalog analyses, connectivity surrogates, dipole fitting) with one worker, because a frozen app cannot safely spawn parallel workers (most visibly on Windows); only MP decomposition (empi) and the IIR filter still use the field. A `pip` install is unaffected. |

## Links

- [User Manual](ide4eeg/USER_MANUAL.md) — full parameter reference and walkthrough. Read it online as [HTML](https://ide4eeg-32a4da.gitlab.io) or [PDF](https://ide4eeg-32a4da.gitlab.io/manual.pdf) (the version + date print on the PDF's title page). Both are **committed artifacts at version-free paths** so their links stay stable across releases; the `pages` CI job only publishes them. Rebuild **both** with `./scripts/build_pdf.sh` after editing the markdown, and commit them — nothing in CI renders the manual, so an unrebuilt edit never reaches the published copies. Requires `pandoc` + **`lualatex`** (`brew install --cask mactex-no-gui` on macOS, `apt install texlive-luatex texlive-fonts-recommended` on Linux — lualatex, *not* xelatex: it renders the GUI's color-emoji icons via HarfBuzz), and it must find a Python that can `import ide4eeg` (run it with the project venv active) or Appendix G is omitted.
- [Contributing](CONTRIBUTING.md) — development setup
- [Maintainer wiki](docs/maintainer-wiki/) — the *why*, the failure history, and the bug-vs-feature [behavioural contract](docs/maintainer-wiki/reference-architecture-contract.md); an LLM-maintained knowledge base (Karpathy's "LLM Wiki" pattern)
- [License](LICENSE) — GPL-3.0
