Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: upstreaming improved device classes from erb-thesis #93

Draft
wants to merge 7 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Docs

on:
push:
branches: [ master, 'dev/*' ]
branches: [ master, develop ]
pull_request:
branches: [ master ]
branches: [ master, develop ]

jobs:
build:
Expand All @@ -29,8 +29,8 @@ jobs:
cd doc && make html
- name: Deploy Docs
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/master'
if: github.ref == 'refs/heads/master' # TODO: Deploy seperate develop-version of docs?
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: doc/_build/html

13 changes: 9 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Test

on:
push:
branches: [ master ]
branches: [ master, develop ]
pull_request:
branches: [ master ]
branches: [ master, develop ]

jobs:
test:
Expand Down Expand Up @@ -60,8 +60,8 @@ jobs:
run: |
python -m pip install --upgrade pip wheel
pip install .
- name: Run eegnb install test
shell: bash
- name: Run eegnb cli test
shell: bash
pip install -U psychtoolbox # JG_ADD
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
Expand All @@ -78,6 +78,11 @@ jobs:
Xvfb :0 -screen 0 1024x768x24 -ac +extension GLX +render -noreset &> xvfb.log &
export DISPLAY=:0
fi
eegnb --help
eegnb runexp --help
- name: Run tests
shell: bash
run: |
pytest

typecheck:
Expand Down
11 changes: 9 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
__pycache__
.venv

*.egg-info/

# Created by tests
.coverage
coverage.xml
htmlcov
prof

# Built as part of docs
doc/auto_examples
doc/_build

# Built by auto_examples
examples/visual_cueing/*.csv

# present for people who use pyenv
.venv

# tests/coverage artifacts
.coverage
coverage.xml
Expand Down
5 changes: 4 additions & 1 deletion doc/getting_started/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Use the following commands to download the repo, create and activate a conda or
git clone https://github.com/NeuroTechX/eeg-notebooks

cd eeg-notebooks

pip install -e .


Expand Down Expand Up @@ -125,6 +125,9 @@ Start a jupyter notebooks session and you will be presented with the eeg-noteboo
subject = 999 # a 'very British number'
record_duration=120

# Initiate EEG device
eeg_device = EEGDevice.create(device=board_name)

# Initiate EEG device
eeg_device = EEG(device=board_name)

Expand Down
10 changes: 5 additions & 5 deletions doc/getting_started/running_experiments.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ The first step is to import all of the necessary library dependencies. These are

```python
from eegnb import generate_save_fn
from eegnb.devices.eeg import EEG
from eegnb.devices import EEGDevice
from eegnb.experiments.visual_n170 import n170
```

Expand All @@ -104,10 +104,10 @@ record_duration = 120
save_fn = generate_save_fn(board_name, experiment, subject, session)
```

Next it is necessary to call the `eegnb.devices.eeg.EEG` class which handles all of the backend processes related to each device.
Next it is necessary to create an instance of the `eegnb.devices.EEGDevice` class which handles all of the backend processes related to each device.

```python
eeg_device = EEG(device=board_name)
eeg_device = EEGDevice.create(device_name=board_name)
```

Finally, we call the `present` method of the class corresponding to our desired experiment, in this case the visual N170. We pass both the EEG device and generated save file name in order to collect and save data. The presentation can also be run without an EEG device/save file for testing and debugging.
Expand All @@ -120,7 +120,7 @@ All together the example script looks like
```python
# Imports
from eegnb import generate_save_fn
from eegnb.devices.eeg import EEG
from eegnb.devices import EEGDevice
from eegnb.experiments.visual_n170 import n170

# Define some variables
Expand All @@ -134,7 +134,7 @@ record_duration = 120
save_fn = generate_save_fn(board_name, experiment, subject, session)

# Setup EEG device
eeg_device = EEG(device=board_name)
eeg_device = EEGDevice.create(device_name=board_name)

# Run stimulus presentation
n170.present(duration=record_duration, eeg=eeg_device, save_fn=save_fn)
Expand Down
11 changes: 5 additions & 6 deletions doc/getting_started/streaming.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ Before getting going with running an experiment, it is important to first verify

The exact steps for this varies with the device (MUSE, OpenBCI, others) and operating system (Windows, Mac, Linux) used. When using these instructions, you should make sure you are consulting the section appropriate for your combination of device and OS.

Initiating an EEG stream is a relatively easy process using the `eegnb.devices.eeg.EEG` class which abstracts the
the various devices and backends behind one easy call.
Initiating an EEG stream is a relatively easy process using the `eegnb.devices.EEGDevice` class which abstracts the various devices and backends behind one easy call.

```python
from eegnb.devices.eeg import EEG
from eegnb.devices import EEGDevice

# define the name for the board you are using and call the EEG object
eeg = EEG(device='cyton')
eeg = EEGDevice.create(device='cyton')

# start the stream
eeg.start()
Expand Down Expand Up @@ -111,10 +110,10 @@ menu pictures below.

Now that we have the COM port, we can initiate the stream by passing it to the EEG device in the object call.
```python
from eegnb.devices.eeg import EEG
from eegnb.devices import EEGDevice

# define the name for the board you are using and call the EEG object
eeg = EEG(
eeg = EEGDevice.create(
device='cyton',
serial_port='COM7'
)
Expand Down
49 changes: 34 additions & 15 deletions eegnb/cli/__main__.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
from eegnb import DATA_DIR
import click
from time import sleep
from os import path
import logging
import os
import shutil
from os import path
from time import sleep

from eegnb import DATA_DIR
from eegnb.datasets.datasets import zip_data_folders

from .introprompt import intro_prompt
from .utils import run_experiment
from eegnb.devices.eeg import EEG
from eegnb.analysis.utils import check_report

logger = logging.getLogger(__name__)


@click.group(name="eegnb")
def main():
"""eeg-notebooks command line interface"""
pass
logging.basicConfig(level=logging.INFO)


@main.command()
Expand All @@ -34,7 +38,7 @@ def runexp(
recdur: float = None,
outfname: str = None,
prompt: bool = False,
dosigqualcheck = True,
dosigqualcheck=True,
):
"""
Run experiment.
Expand All @@ -59,31 +63,34 @@ def runexp(
if prompt:
eeg, experiment, recdur, outfname = intro_prompt()
else:
from .utils import run_experiment
from eegnb.devices import EEGDevice

if eegdevice == "ganglion":
# if the ganglion is chosen a MAC address should also be provided
eeg = EEG(device=eegdevice, mac_addr=macaddr)
# if the ganglion is chosen a MAC address should also be proviced
eeg = EEGDevice.create(device_name=eegdevice, mac_addr=macaddr)
else:
eeg = EEG(device=eegdevice)
if eegdevice:
eeg = EEGDevice.create(device_name=eegdevice)
else:
print("No EEG device provided, using a synthetic one.")

def askforsigqualcheck():
do_sigqual = input("\n\nRun signal quality check? (y/n). Recommend y \n")
if do_sigqual == 'y':
if do_sigqual == "y":
check_report(eeg)
elif do_sigqual != 'n':
elif do_sigqual != "n":
"Sorry, didn't recognize answer. "
askforsigqualcheck()

if dosigqualcheck:
askforsigqualcheck()


run_experiment(experiment, eeg, recdur, outfname)

print(f"\n\n\nExperiment complete! Recorded data is saved @ {outfname}")




@main.command()
@click.option("-ed", "--eegdevice", help="EEG device to use", required=True)
def checksigqual(eegdevice: str):
Expand Down Expand Up @@ -124,7 +131,7 @@ def runzip(experiment: str, site: str, prompt: bool = False):

$ eegnb runzip -ex visual-N170
$ eegnb runzip -ex visual-N170 -s local-ntcs-2

Launch the interactive command line to select experiment

$ eegnb runzip -ip
Expand Down Expand Up @@ -191,5 +198,17 @@ def localdata_report():
print(" {}".format(items))


def test_cli():
from click.testing import CliRunner

runner = CliRunner()
result = runner.invoke(main, ["--help"])
assert result.exit_code == 0

runner = CliRunner()
result = runner.invoke(runexp, ["--help"])
assert result.exit_code == 0


if __name__ == "__main__":
main()
Loading