Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 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
a7495f9
Merge branch 'incoming' into dev/prvep_experiment_with_docs
pellet May 6, 2026
f421175
photodiode stuff wip
pellet May 7, 2026
aa76b6b
Merge branch 'release/build-fixes' into dev/prvep_experiment_with_docs
pellet May 7, 2026
ae654f9
removed unneeded code and fix crash in non vr mode.
pellet May 7, 2026
b922d4e
Merge branch 'release/build-fixes' into dev/prvep_experiment_with_docs
pellet May 8, 2026
40d1ffe
vr telemetry/push marker clean up
pellet May 8, 2026
cf109ef
Refactor VEP analysis and visualization
pellet May 11, 2026
a3d5427
revert
pellet May 12, 2026
f4f2003
simplified markers
pellet May 14, 2026
f166658
remove placeholder
pellet May 15, 2026
94bfe1a
removed flip_time prototype
pellet May 15, 2026
99190fb
updated ordering
pellet May 15, 2026
887359c
fixes
pellet May 15, 2026
e561fbf
improve perf
pellet May 16, 2026
6dcaca9
fix quality check
pellet May 16, 2026
8082baf
wip
pellet May 16, 2026
074e015
fixed spinner
pellet May 17, 2026
cd05828
remove unneeded stuff and write file at end
pellet May 17, 2026
47b79d5
move vr stats into correct loc
pellet May 18, 2026
0df827c
removed unneeded performance diagnostics and refactored high priority…
pellet May 18, 2026
92d3570
refactored diagnostic stuff
pellet May 18, 2026
a41c516
make opt-in only
pellet May 18, 2026
ef12e14
make check size configurable
pellet May 22, 2026
cbda85e
updated peak detection
pellet May 23, 2026
dbce5ac
cleanup
pellet May 23, 2026
9faf2b5
cleaned up instructions and fixation size
pellet May 23, 2026
68d5c14
Merge branch 'master' of github.com:pellet/EEG-ExPy into dev/prvep_ex…
pellet May 23, 2026
296bc59
fixes
pellet May 23, 2026
1806119
removed unused pacing code
pellet May 23, 2026
be7051a
fix case
pellet May 23, 2026
4f0bf33
anchor to 85
pellet May 23, 2026
11475c7
clean up and add jitter arg
pellet May 24, 2026
8aa0e29
remove unneeded vr option
pellet May 24, 2026
e9c0051
better differentiate between dark stim and dropout
pellet May 24, 2026
a067029
diode functions
pellet May 25, 2026
e058adf
diode updates
pellet May 25, 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ __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
Expand Down
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
337 changes: 337 additions & 0 deletions doc/experiments/vprvep.rst

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions doc/getting_started/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ Use the following commands to download the repo, create and activate a conda or

**Environment file options**

*Python 3.8 - 3.10:*
*Python 3.10:*

- `eeg-expy-full`: Install all dependencies

- `eeg-expy-stimpres`: Stimulus presentation

- `eeg-expy-streamstim`: Combined streaming and stimulus presentation

*Python 3.8 - 3.13:*
*Python 3.10 - 3.13:*

- `eeg-expy-docsbuild`: Documentation

Expand All @@ -68,7 +68,7 @@ Use the following commands to download the repo, create and activate a conda or

# Create conda environment from chosen eeg-expy-*.yml
# The Python version will be pinned by the environment file
conda env create -n eeg-expy --file=environments/eeg-expy-full.yml
conda env create -n eeg-expy -f environments/eeg-expy-full.yml

# Activate the environment
conda activate eeg-expy
Expand Down
162 changes: 81 additions & 81 deletions doc/getting_started/loading_and_saving.md
Original file line number Diff line number Diff line change
@@ -1,82 +1,82 @@
# Loading and Saving Data
Knowing where the data is saved is integral to the functionality of EEG Notebooks. EEG Notebooks saves data to a default location in a hidden directory. From this directory, the individual files can be found based on a folder structure outlined below in the **naming convention.**
## Locating the Default Data Directory
#### Windows 10
The default directory is found at the location `C:\Users\*USER_NAME*\.eegnb` an example of which is pictured below.
![fig](../img/windows_default_directory.PNG)
#### Linux
#### MacOS
## Changing the Default Data Directory
The default directory for saving data is automatically set within the library. If you want to save and analyze data to/from a new directory, it must be passed as a parameter to both the `eegnb.generate_save_fn()` and `eegnb.analysis.load_data()` functions.
**Saving to new directory:**
``` python
from eegnb import generate_save_fn
from eegnb.experiments.visual_n170 import n170
# Define session parameters
board = 'cyton'
experiment = 'visual-N170
subject = 1
session = 1
# Define new directory and generate save filename
new_dir = 'C:/Users/Jadin/Documents/EEG_Notebooks_Data'
save_fn = generate_save_fn(board, experiment, subject, session, new_dir)
# Continue to run experiment as normal...
```
**Loading from new directory:**
``` python
from eegnb.analysis.utils import load_data
# Define parameters for session you want to load
board = 'cyton'
experiment = 'visual-N170
subject = 1
session = 1
# Define new directory
new_dir = 'C:/Users/Jadin/Documents/EEG_Notebooks_Data'
# Load data
raw = load_data(
subject_id = subject,
session_nb = session,
device_name = board,
experiment = experiment,
data_dir = new_dir
)
```
## Naming Convention
From the specified data directory, EEG notebooks then follows a specific set of naming conventions to define subdirectories and save the data. The full path ends up taking the form
```
DATA_DIR\experiment\site\device\subject#\session#\file_name.csv
```
Each field is explained below:
**Experiment:** This part is the name of the experiment being run. Example names of experiments as they appear in the example datasets are shown below.
```
visual-N170
visual-P300
visual-SSVEP
```
**Site:** The site refers to the recording location, or generally the machine it was recorded to. If you are saving and analyzing only your own data on your local machine, you do not need to specify your site name as it will default to 'local'. When loading example datasets however, it is necessary to specify from which site you would like to load data.
**Device:** The name of the device being recorded from.
**Subject #:** When entering subject ID as a parameter, you only need to specify the integer value. The integer will be formatted to `subjectXXXX` where "XXXX" is a four-digit representation of the integer ID#.
**Session #:** A session in this case would be the full period of time which you have the device on and are taking multiple recordings. For example: if you put the headset on and take five recordings, all five of these recording would belong to session number 1. Once you take a break from consecutive recordings, then this would constitute a new session. Just like the subject ID, this value is passed as an integer and gets converted to a read-able format.
**File name:** The file name is automatically generated in the format `recording_date_time.csv`
# Loading and Saving Data
Knowing where the data is saved is integral to the functionality of EEG Notebooks. EEG Notebooks saves data to a default location in a hidden directory. From this directory, the individual files can be found based on a folder structure outlined below in the **naming convention.**

## Locating the Default Data Directory

#### Windows 10
The default directory is found at the location `C:\Users\*USER_NAME*\.eegnb` an example of which is pictured below.
![fig](../img/windows_default_directory.PNG)

#### Linux

#### MacOS

## Changing the Default Data Directory
The default directory for saving data is automatically set within the library. If you want to save and analyze data to/from a new directory, it must be passed as a parameter to both the `eegnb.generate_save_fn()` and `eegnb.analysis.load_data()` functions.

**Saving to new directory:**
``` python
from eegnb import generate_save_fn
from eegnb.experiments.visual_n170 import n170

# Define session parameters
board = 'cyton'
experiment = 'visual-N170
subject = 1
session = 1

# Define new directory and generate save filename
new_dir = 'C:/Users/Jadin/Documents/EEG_Notebooks_Data'
save_fn = generate_save_fn(board, experiment, subject, session, new_dir)

# Continue to run experiment as normal...
```

**Loading from new directory:**
``` python
from eegnb.analysis.utils import load_data

# Define parameters for session you want to load
board = 'cyton'
experiment = 'visual-N170
subject = 1
session = 1

# Define new directory
new_dir = 'C:/Users/Jadin/Documents/EEG_Notebooks_Data'

# Load data
raw = load_data(
subject_id = subject,
session_nb = session,
device_name = board,
experiment = experiment,
data_dir = new_dir
)
```

## Naming Convention
From the specified data directory, EEG notebooks then follows a specific set of naming conventions to define subdirectories and save the data. The full path ends up taking the form
```
DATA_DIR\experiment\site\device\subject#\session#\file_name.csv
```
Each field is explained below:

**Experiment:** This part is the name of the experiment being run. Example names of experiments as they appear in the example datasets are shown below.
```
visual-N170
visual-P300
visual-SSVEP
```

**Site:** The site refers to the recording location, or generally the machine it was recorded to. If you are saving and analyzing only your own data on your local machine, you do not need to specify your site name as it will default to 'local'. When loading example datasets however, it is necessary to specify from which site you would like to load data.

**Device:** The name of the device being recorded from.

**Subject #:** When entering subject ID as a parameter, you only need to specify the integer value. The integer will be formatted to `subjectXXXX` where "XXXX" is a four-digit representation of the integer ID#.

**Session #:** A session in this case would be the full period of time which you have the device on and are taking multiple recordings. For example: if you put the headset on and take five recordings, all five of these recording would belong to session number 1. Once you take a break from consecutive recordings, then this would constitute a new session. Just like the subject ID, this value is passed as an integer and gets converted to a read-able format.

**File name:** The file name is automatically generated in the format `recording_date_time.csv`

### Examples
3 changes: 3 additions & 0 deletions doc/getting_started/streaming.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ be run to begin the notebooks interfacing with the bluemuse backend.
**Needed Parameters:**
**Optional Parameters:**

**Cyton USB-Serial Latency (Windows):**
A note on Cyton USB-serial latency: the Windows FTDI driver default `LatencyTimer` of 16 ms causes batched marker delivery and corrupts millisecond-grade marker timing. The experiment scripts assert `LatencyTimer = 1 ms` at startup; recordings predating this assertion contain a ~15 ms hardware buffering lag on the marker channel that must be subtracted before comparing absolute latencies across sessions.

### OpenBCI Cyton + Daisy
![fig](../img/cyton_daisy.png)
**Device Name:** *'cyton_daisy'* or *'cyton_daisy_wifi'* with WiFi Shield
Expand Down
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
experiments/vn170
experiments/vp300
experiments/vssvep
experiments/vprvep
experiments/cueing
experiments/gonogo
experiments/all_examples
Expand Down
2 changes: 1 addition & 1 deletion eegnb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def _get_recording_dir(
"""A subroutine of get_recording_dir that accepts subject and session as strings"""
# folder structure is /DATA_DIR/experiment/board_name/site/subject/session/*.csv
recording_dir = (
Path(data_dir) / experiment / site / board_name / subject_str / session_str
Path(data_dir or DATA_DIR) / experiment / site / board_name / subject_str / session_str
)

# check if directory exists, if not, make the directory
Expand Down
1 change: 1 addition & 0 deletions eegnb/analysis/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from eegnb.analysis import vep_utils # noqa: F401
Loading
Loading