Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
fb931fa
pr vep stuff
pellet Apr 12, 2026
0497302
rename VisualVEP to VisualGratingVEP and vvep.rst to vprvep.rst
pellet Apr 12, 2026
aae0f14
feat: add pattern reversal VEP visualization example and utility func…
pellet Apr 12, 2026
31b8994
feat: add Cyton config constants and PRVEP run experiment example
pellet Apr 12, 2026
d6f2470
fix docs build: add python-dotenv to docsbuild requirements
pellet Apr 12, 2026
cfd47b1
prepare PR-VEP example for fetch_dataset; exclude from CI until data …
pellet Apr 12, 2026
b84d736
fix analysis/utils.py imports: lazy-load EEG and pynput to unblock do…
pellet Apr 12, 2026
1399491
fix NameError: add __future__ annotations to defer EEG type annotatio…
pellet Apr 12, 2026
d0a2ac6
fix docs CI: remove root examples dir and visual_vep from gallery unt…
pellet Apr 12, 2026
a066755
docs: update PR-VEP intro to reference Cyton and electrode placement
pellet Apr 12, 2026
270a197
docs: update PR-VEP electrode placement section for Cyton
pellet Apr 12, 2026
b67fc9a
ci: deploy docs on dev/* branches as well as master
pellet Apr 12, 2026
4fd9de6
docs: replace remaining Muse references with Cyton in PR-VEP docs
pellet Apr 12, 2026
46950bf
docs: document refresh rate requirements and effect on P100 latency p…
pellet Apr 12, 2026
07934c8
docs: restructure PR-VEP page and add visual correction section
pellet Apr 13, 2026
9457817
docs: remove API Reference section from PR-VEP page for consistency
pellet Apr 13, 2026
a2670df
docs: set PR-VEP example refresh rate to 120 Hz for Quest 2
pellet Apr 13, 2026
2940599
feat: sub-sample P100 peak interpolation and high-precision defaults
pellet Apr 13, 2026
ddb85eb
docs: update photodiode sync patch wording
pellet Apr 13, 2026
72c670b
docs: remove gc/rush detail from PR-VEP page (handled by base class)
pellet Apr 13, 2026
feb78d2
feat: add longitudinal P100 tracking notebook and docs section
pellet Apr 13, 2026
3b60a29
add missing req
pellet Apr 14, 2026
e03347d
wip experiment example cleanup
pellet Apr 14, 2026
434a912
fixed errors
pellet Apr 14, 2026
88234cf
cleanup
pellet Apr 15, 2026
4ab3d40
vr fixes
pellet Apr 16, 2026
b83cf44
fix settings
pellet Apr 16, 2026
3b3ae5d
fix positions
pellet Apr 16, 2026
058a31b
cyton amplification config fixes
pellet Apr 16, 2026
00e2236
first run of analysis
pellet Apr 16, 2026
5ac048c
gain fixes for active electrodes
pellet Apr 17, 2026
c5419d1
feed vr compositor during soa wait
pellet Apr 18, 2026
99a9b04
experiment fixes for running cap montage
pellet Apr 19, 2026
fb87079
don't write to the sidecar if the eeg connection/marker fails
pellet Apr 19, 2026
4031f22
reword
pellet Apr 19, 2026
39ee274
Update plot_vep to use fixed non-cascading windows
pellet Apr 19, 2026
1a06310
add check latency is set to 1ms for cyton on windows.
pellet Apr 20, 2026
f8ca6b4
examples updates
pellet Apr 20, 2026
dbfbbd2
correctly calculate VR stereoscopic axis instead of constant.
pellet Apr 22, 2026
8a0cc73
cleaned up vr code
pellet Apr 22, 2026
ef0815a
moved more vr stuff out and made the stimulus more inline with iscev …
pellet Apr 22, 2026
9d3f4d3
added updated visualization
pellet Apr 22, 2026
af6cd75
fixed import
pellet Apr 22, 2026
6f0f655
fixed again
pellet Apr 22, 2026
054521d
dropped support for python 3.8
pellet Apr 23, 2026
4a7d01c
try building newer versions of python
pellet Apr 23, 2026
50c83ad
fixed syntax
pellet Apr 23, 2026
b223990
drop support for py3.9
pellet Apr 23, 2026
7d5b92a
stop crashing due to no ftdi driver
pellet Apr 23, 2026
af80314
bump pyobjc for psychopy
pellet Apr 23, 2026
916317b
no more 3.9
pellet Apr 23, 2026
4cfbaae
better handle sound on macos builds
pellet Apr 23, 2026
9f0a7af
update docs
pellet Apr 23, 2026
46decaf
fix conda for experimental builds
pellet Apr 23, 2026
0780fd2
try proper support for newer python versions on CI
pellet Apr 23, 2026
aee10c0
add the tests to the streaming section for ci.
pellet Apr 24, 2026
a5a2c1f
try having builds work for streaming environment
pellet Apr 24, 2026
faccd57
build fix ups
pellet Apr 24, 2026
6cbf190
clean up refresh rate detection
pellet Apr 24, 2026
ed00eb6
fix example
pellet Apr 24, 2026
b8de4d2
doc update
pellet Apr 27, 2026
93f92ef
updated experiment to use alternating block sizes
pellet Apr 27, 2026
b5580ce
updated montage
pellet Apr 27, 2026
3976a3f
feat(vep): integrate automated dataset fetch and UX enhancements
pellet May 4, 2026
891e4c5
refactor(vep): remove legacy v1 marker support (KISS)
pellet May 4, 2026
5d16ed5
refactor: remove backwards compatible event code from viz script
pellet May 4, 2026
4eb0fe4
feat(vep): enhance visualization and update reference scheme
pellet May 4, 2026
9839fef
feat(vep): compute BM12 topology check by locally re-referencing to M2
pellet May 4, 2026
dc10db5
feat(analysis): implement robust local-maximum peak finder
pellet May 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Force LF line endings for WSL and cross-platform (Linux/Mac/GitHub Actions) compatibility
# This prevents obscure bugs when running Windows-edited scripts on Linux runners.
* text=auto eol=lf

*.py text eol=lf
*.rst text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.cfg text eol=lf
*.toml text eol=lf
*.ipynb text eol=lf

*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.pdf binary
32 changes: 32 additions & 0 deletions .github/actions/setup-conda-env/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Set up conda env
description: >
Install Miniconda and create/activate an EEG-ExPy conda environment from
the given env yml. Shared by the Test and Typecheck jobs so the two
don't drift apart. Environment name is not set in the yml files so local
installs can use any name they like.

inputs:
environment-file:
required: true
description: Path to the conda environment yml file to install from.
activate-environment:
required: true
description: Name to give the created environment.
python-version:
required: false
description: >
Python version to pin (e.g. '3.8'). Overrides the version conda would
otherwise resolve from the environment file's constraints. When omitted,
conda resolves freely within the environment file's range.

runs:
using: composite
steps:
- uses: conda-incubator/setup-miniconda@v3
with:
environment-file: ${{ inputs.environment-file }}
activate-environment: ${{ inputs.activate-environment }}
python-version: ${{ inputs.python-version }}
auto-activate-base: false
channels: conda-forge
miniconda-version: "latest"
39 changes: 13 additions & 26 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,20 @@ on:
jobs:
build:
runs-on: ubuntu-22.04
defaults:
run:
shell: bash -el {0}
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.8

- name: Install dependencies
run: |
make install-deps-apt
python -m pip install --upgrade pip wheel
python -m pip install attrdict

make install-deps-wxpython

- name: Build project
run: |
make install-docs-build-dependencies
fetch-depth: 0

- name: Set up conda env
uses: ./.github/actions/setup-conda-env
with:
environment-file: environments/eeg-expy-docsbuild.yml
activate-environment: eeg-expy-docsbuild

- name: Get list of changed files
id: changes
Expand All @@ -40,21 +31,20 @@ jobs:
git diff --name-only origin/master...HEAD > changed_files.txt
cat changed_files.txt


- name: Determine build mode
id: mode
run: |
if grep -vqE '^examples/.*\.py$' changed_files.txt; then
echo "FULL_BUILD=true" >> $GITHUB_ENV
echo "Detected non-example file change. Full build triggered."
else
CHANGED_EXAMPLES=$(grep '^examples/.*\.py$' changed_files.txt | paste -sd '|' -)
# || true prevents grep's exit code 1 (no matches) from aborting the step
CHANGED_EXAMPLES=$(grep '^examples/.*\.py$' changed_files.txt | paste -sd '|' - || true)
echo "FULL_BUILD=false" >> $GITHUB_ENV
echo "CHANGED_EXAMPLES=$CHANGED_EXAMPLES" >> $GITHUB_ENV
echo "Changed examples: $CHANGED_EXAMPLES"
fi


- name: Cache built documentation
id: cache-docs
uses: actions/cache@v4
Expand All @@ -65,15 +55,12 @@ jobs:
restore-keys: |
${{ runner.os }}-sphinx-


- name: Build docs
run: |
make docs
run: make docs


- name: Deploy Docs
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/master' # TODO: Deploy seperate develop-version of docs?
if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/dev/')
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: doc/_build/html
58 changes: 32 additions & 26 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,47 @@ jobs:
defaults:
run:
shell: bash -el {0}
continue-on-error: ${{ matrix.experimental == true }}
strategy:
fail-fast: false
matrix:
os: ['ubuntu-22.04', windows-latest, macOS-latest]
python_version: ['3.8']
os: [ubuntu-22.04, windows-latest, macOS-latest]
python_version: ['3.10']
env_file: [environments/eeg-expy-full.yml]
env_name: [eeg-expy-full]
include:
# PsychoPy currently restricted to <= 3.10
# Experimental Full Build: Catch regressions on 3.11 early
- os: ubuntu-22.04
python_version: '3.10'
python_version: '3.11'
experimental: true
env_file: environments/eeg-expy-full.yml
env_name: eeg-expy-full

# Experimental Streaming Builds: Verify acquisition/analysis on 3.12+
- os: ubuntu-22.04
python_version: '3.12'
experimental: true
env_file: environments/eeg-expy-streaming.yml
env_name: eeg-expy-streaming
- os: ubuntu-22.04
python_version: '3.13'
experimental: true
env_file: environments/eeg-expy-streaming.yml
env_name: eeg-expy-streaming

steps:
- uses: actions/checkout@v2
- name: Install APT dependencies
if: "startsWith(runner.os, 'Linux')"
run: |
make install-deps-apt
- name: Install conda
uses: conda-incubator/setup-miniconda@v3
- name: Set up conda env
uses: ./.github/actions/setup-conda-env
with:
environment-file: environments/eeg-expy-full.yml
auto-activate-base: false
environment-file: ${{ matrix.env_file }}
activate-environment: ${{ matrix.env_name }}
python-version: ${{ matrix.python_version }}
activate-environment: eeg-expy-full
channels: conda-forge
miniconda-version: "latest"

- name: Fix PsychXR numpy dependency DLL issues (Windows only)
if: matrix.os == 'windows-latest'
run: |
conda install --force-reinstall numpy

- name: Run eegnb install test
- name: Run eeg-expy install test
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
Xvfb :0 -screen 0 1024x768x24 -ac +extension GLX +render -noreset &> xvfb.log &
Expand All @@ -58,7 +67,7 @@ jobs:
Xvfb :0 -screen 0 1024x768x24 -ac +extension GLX +render -noreset &> xvfb.log &
export DISPLAY=:0
fi
make test PYTEST_ARGS="--ignore=tests/test_run_experiments.py"
make test


typecheck:
Expand All @@ -71,19 +80,16 @@ jobs:
fail-fast: false
matrix:
os: ['ubuntu-22.04']
python_version: [3.9]
python_version: ['3.10']

steps:
- uses: actions/checkout@v2
- name: Install conda
uses: conda-incubator/setup-miniconda@v3
- name: Set up conda env
uses: ./.github/actions/setup-conda-env
with:
environment-file: environments/eeg-expy-full.yml
auto-activate-base: false
python-version: ${{ matrix.python_version }}
activate-environment: eeg-expy-full
channels: conda-forge
miniconda-version: "latest"
python-version: ${{ matrix.python_version }}
- name: Typecheck
run: |
make typecheck
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ __pycache__
# Built as part of docs
doc/auto_examples
doc/_build
doc/generated/
doc/sg_execution_times.rst

# Built by auto_examples
examples/visual_cueing/*.csv

# Jupytext-paired notebooks (the .py is the source of truth; .ipynb is auto-paired)
**.ipynb

# tests/coverage artifacts
.coverage
coverage.xml
Expand All @@ -18,4 +23,4 @@ htmlcov
# PyCharm
.idea/

**/.DS_Store
**/.DS_Store
19 changes: 19 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import importlib.util


def _is_available(module_name: str) -> bool:
try:
return importlib.util.find_spec(module_name) is not None
except (ImportError, ValueError):
return False


collect_ignore: list[str] = []

if not _is_available("psychopy"):
collect_ignore += [
"eegnb/experiments",
"eegnb/devices/vr.py",
]
elif not _is_available("psychxr"):
collect_ignore += ["eegnb/devices/vr.py"]
6 changes: 3 additions & 3 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,9 @@ def setup(app):

# Configurations for sphinx gallery

sphinx_gallery_conf = {'filename_pattern': '(?=.*r__)(?=.*.py)',
'examples_dirs': ['../examples','../examples/visual_n170', '../examples/visual_p300','../examples/visual_ssvep', '../examples/visual_cueing', '../examples/visual_gonogo'],
'gallery_dirs': ['auto_examples','auto_examples/visual_n170', 'auto_examples/visual_p300','auto_examples/visual_ssvep', 'auto_examples/visual_cueing', 'auto_examples/visual_gonogo'],
sphinx_gallery_conf = {'filename_pattern': '(?=.*r__)(?=.*.py)',
'examples_dirs': ['../examples/visual_n170', '../examples/visual_p300','../examples/visual_ssvep', '../examples/visual_cueing', '../examples/visual_gonogo'],
'gallery_dirs': ['auto_examples/visual_n170', 'auto_examples/visual_p300','auto_examples/visual_ssvep', 'auto_examples/visual_cueing', 'auto_examples/visual_gonogo'],
'within_subsection_order': FileNameSortKey,
'default_thumb_file': 'img/eeg-notebooks_logo.png',
'backreferences_dir': 'generated', # Where to drop linking files between examples & API
Expand Down
Loading
Loading