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

CI #166

Merged
merged 7 commits into from
Aug 4, 2021
Merged

CI #166

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
100 changes: 100 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: BciPy

on:
push:
branches:
- main
pull_request:
branches:
- '**'

jobs:
build-ubuntu:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
sudo apt-get install libgtk-3-dev
sudo apt-get install freeglut3-dev
sudo apt-get install freetype*
sudo apt-get install portaudio*
sudo apt-get install libsndfile*
sudo apt-get install xvfb
python -m pip install --upgrade pip
pip install -r dev_requirements.txt
pip install -e .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 bcipy
- name: Unit test
run: |
xvfb-run coverage run --branch --source=bcipy -m pytest --mpl -k "not slow"

build-windows:

runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r dev_requirements.txt
pip install -e .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 bcipy
- name: Unit test
run: |
coverage run --branch --source=bcipy -m pytest --mpl -k "not slow"

build-macos:

runs-on: macos-latest
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r dev_requirements.txt
pip install -e .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 bcipy
- name: Unit test
run: |
coverage run --branch --source=bcipy -m pytest --mpl -k "not slow"
154 changes: 74 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,40 @@
# Brain- Computer Interface Codebase
------------------------------------
# BciPy: Brain-Computer Interface Software in Python

### What is it?

It is Brain-computer interface software written in Python. It can function as a standalone or you can take the tools you need and start coding your own system. See our official BciPy documentation including affiliations and more context information here: https://bcipy.github.io/ (in progress).
[![BciPy](https://github.com/CAMBI-tech/BciPy/actions/workflows/main.yml/badge.svg)](https://github.com/CAMBI-tech/BciPy/actions/workflows/main.yml)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg)](https://github.com/CAMBI-tech/BciPy/fork)
[![Follow on Twitter](https://img.shields.io/twitter/follow/cambi_tech?label=Follow&style=social)](https://twitter.com/cambi_tech)

It should, based on our dependencies, work on most recent operating systems, however it has only been verified on Windows (7 & 10 Pro) and Mac OSx (High Sierra & Mojave) at this time. It won't build as is on Linux. Some additional work will be needed to install WxPython and pylsl.

### Contributions Welcome!
BciPy is a library for conducting Brain-Computer Interface experiments in Python. It functions as a standalone application for experimental data collection or you can take the tools you need and start coding your own system. See our official BciPy documentation including affiliations and more context information [here](https://bcipy.github.io/) (in progress).

This is our first release. It is verified using LSL with DSI and gtec for the Calibration modes only at this time with both image and text stimuli. It comes with a fake data server to help you develop while mocking real time EEG acquisition. We are taking all suggestions at this time for additions, eventually we'll make a contributions wishlist. If you want to be added to the development team, reach out to us and we'll add you to the team slack.
It will run on the latest windows, linux and macos. Other versions may work as well, but are not guaranteed. To see supported versions and operating systems as of this release see here: [BciPy Builds](https://github.com/CAMBI-tech/BciPy/actions/workflows/main.yml).

*Please cite us when using!*

```
Memmott, T., Koçanaoğulları, A., Lawhead, M., Klee, D., Dudy, S., Fried-Oken, M., & Oken, B. (2021). BciPy: brain–computer interface software in Python. Brain-Computer Interfaces, 1-18.
```

## Paradigms
-----------
### Contributions Welcome!

*RSVPKeyboard*
If you want to be added to the development team, reach out to us and we'll add you to the team slack!

```
*RSVP KeyboardTM* is an EEG (electroencephalography) based BCI (brain
computer interface) typing system. It utilizes a visual presentation technique
called rapid serial visual presentation (RSVP). In RSVP, the options are
presented rapidly at a single location with a temporal separation. Similarly
in RSVP KeyboardTM, the symbols (the letters and additional symbols) are
shown at the center of screen. When the subject wants to select a symbol,
they await the intended symbol during the presentation and elicit a p300 response to a target symbol.
```
### Contribution Guidelines

We follow and will enforce the contributor's covenant to foster a safe and inclusive environment for this open source software, please reference this link for more information: https://www.contributor-covenant.org/

Other guidelines:
- All added features require tests and a demo.
- All tests must pass to merge, even if they are seemingly unrelated to your work.
- Use Spaces, not Tabs.
- Use informative names for functions and classes.
- Document the input and output of your functions / classes in the code. eg in-line commenting and typing
- Do not push IDE or other local configuration files.
- All new modules or major functionality should be documented outside of the code with a README.md.
See README.md in repo or go to this site for inspiration: https://github.com/matiassingers/awesome-readme. Always use a Markdown interpreter before pushing. There are many free online or your IDE may come with one.

See this resource for examples: http://docs.python-guide.org/en/latest/writing/style/

## Dependencies
---------------
Expand All @@ -40,9 +44,9 @@ This project requires Python > 3.6.5 and other packages defined in the requireme
## Installation
---------------

#### BCI Setup
#### BciPy Setup

In order to run BCI suite on your computer, first install **Python 3** [from here.](https://www.python.org/downloads/)
In order to run BciPy on your computer, first install **Python 3** [from here.](https://www.python.org/downloads/)

You must install Docker and Docker-Machine to use the Language Model developed by CSLU. There are instructions in the language model directory for getting the image you need (think of it as a callable server). You'll also need to download and load the language model [images](https://drive.google.com/drive/folders/1OYpUYASAceb60b2c5obyYytEZ0AZrajY?usp=sharing). If not using or rolling your own, set fake_lm to true in the parameters.json file.

Expand All @@ -63,7 +67,7 @@ Alternately, if [Make](http://www.mingw.org/) is installed, you may run the foll
make dev-install
```

## Usage Locally
#### Usage Locally

Start by running `python bcipy/gui/BCInterface.py` in your command prompt or terminal. This will run the GUI. You may also use the command `make bci-gui`. You may also invoke the experiment directly using command line tools from bcipy.

Expand All @@ -75,17 +79,37 @@ Ex. `bcipy --user "bci_user" --task "RSVP Calibration"`

Use the help flag to see other available input options: `bcipy --help`

## Example usage as a package
##### Example usage as a package

```python
from bcipy.helpers import system_utils
system_utils.get_system_info()
```

## Modules and Vital Functions
------------------------------
## Glossary
-----------

***Stimuli***: A single letter, tone or image shown (generally in an inquiry). Singular = stimulus, plural = stimuli.

***Trial***: A collection of data after a stimuli is shown. A----

This a list of the major modules and their functionality. Each module will contain its own README, demo and test scripts. Please check them out for more information!
***Inquiry***: The set of stimuli after a fixation cross in a spelling task to gather user intent. A ---- B --- C ----

***Series***: Each series contains at least one inquiry. A letter/icon decision is made after a series in a spelling task.

***Session***: Data collected for a task. Comprised of metadata about the task and a list of Series.

***Task***: An experimental design with stimuli, trials, inquiries and series for use in BCI. For instance, "RSVP Calibration" is a task.

***Mode***: Common design elements between task types. For instance, Calibration and Free Spelling are modes.

***Paradigm***: Display paradigm with unique properties and modes. Ex. Rapid-Serial Visual Presentation (RSVP), Matrix Speller, Steady-State Visual Evoked Potential (SSVEP).


## Core Modules
---------------

This a list of the major modules and their functionality. Each module will contain its own README, demo and tests. Please check them out for more information!

- `acquisition`: acquires data, gives back desired time series, saves to file at end of session.
- `display`: handles display of stimuli on screen and passes back stimuli timing.
Expand All @@ -99,36 +123,35 @@ This a list of the major modules and their functionality. Each module will conta
- `feedback`: feedback mechanisms for sound and visual stimuli.
- `main`: executor of experiments. Main entry point into the application

## Demo and Tests
-----------------

All major functions and modules have demo and test files associated with them which may be run locally. This should help orient you to the functionality as well as serve as documentation. *If you add to the repo, you should be adding tests and fixing any test that fail when you change the code.*
## Paradigms
------------

For example, you may run the main BciPy demo by:

`python demo/bci_main_demo.py`
> RSVPKeyboard

This demo will load in parameters and execute a demo task defined in the file. There are demo files for all modules listed above except language_model, helpers, and utils. Run them as a python script!

This repository uses pytest for execution of tests. You may execute them by:
```
*RSVP KeyboardTM* is an EEG (electroencephalography) based BCI (brain
computer interface) typing system. It utilizes a visual presentation technique
called rapid serial visual presentation (RSVP). In RSVP, the options are
presented rapidly at a single location with a temporal separation. Similarly
in RSVP KeyboardTM, the symbols (the letters and additional symbols) are
shown at the center of screen. When the subject wants to select a symbol,
they await the intended symbol during the presentation and elicit a p300 response to a target symbol.
```

`py.test` or `pytest` depending on your OS
## Demo
--------

## Contribution Guidelines
--------------------------
All major functions and modules have demo and test files associated with them which may be run locally. This should help orient you to the functionality as well as serve as documentation. *If you add to the repo, you should be adding tests and fixing any test that fail when you change the code.*

We follow and will enforce the contributor's covenant to foster a safe and inclusive environment for this open source software, please reference this link for more information: https://www.contributor-covenant.org/
For example, you may run the main BciPy demo by:

1. All added code will need tests and a demo (if a large feature).
2. All tests must pass to merge, even if they are seemingly unrelated to your task.
3. Pull requests must be tested locally and by the requester on a different computer.
4. Use Spaces, not Tabs.
5. Use informative names for functions and classes.
6. Document the input and output of your functions / classes in the code. eg in-line commenting
7. Do not push IDE or other local configuration files.
8. All new modules or major functionality should be documented outside of the code with a README.md. See README.md in repo or go to this site for inspiration: https://github.com/matiassingers/awesome-readme. Always use a Markdown interpreter before pushing. There are many free online or your IDE may come with one.
`python demo/bci_main_demo.py`

This demo will load in parameters and execute a demo task defined in the file. There are demo files for all modules listed above except language_model, helpers, and utils. Run them as a python script!

Use this resource for examples: http://docs.python-guide.org/en/latest/writing/style/

## Testing
----------
Expand Down Expand Up @@ -169,6 +192,7 @@ make coverage-html
```

## Linting
----------

This project enforces `PEP` style guidelines using [flake8](http://flake8.pycqa.org/en/latest/).

Expand All @@ -190,39 +214,9 @@ Alternately, if Make is installed, you may run the follow command to run autopep
make lint
```

## Glossary
-----------

***Stimuli***: A single letter, tone or image shown (generally in an inquiry). Singular = stimulus, plural = stimuli.

***Trial***: A collection of data after a stimuli is shown. A----

***Inquiry***: The set of stimuli after a fixation cross in a spelling task to gather user intent. A ---- B --- C ----

***Series***: Each series contains at least one inquiry. A letter/icon decision is made after a series in a spelling task.

***Session***: Data collected for a task. Comprised of metadata about the task and a list of Series.

***Task***: An experimental design with stimuli, trials, inquiries and series for use in BCI. For instance, "RSVP Calibration" is a task.

***Mode***: Common design elements between task types. For instance, Calibration and Free Spelling are modes.

***Paradigm***: Display paradigm with unique properties and modes. Ex. Rapid-Serial Visual Presentation (RSVP), Matrix Speller, Steady-State Visual Evoked Potential (SSVEP).


## Authorship
--------------
## Contributors
---------------

- Tab Memmott (OHSU)
- Matthew Lawhead (OHSU)
- Aziz Kocanaogullari (NEU)
- Shiran Dudy (OHSU)
- Dani Smektala (OHSU)
- Ian Jackson (Reed)
- Alister Cedeño (OHSU)
- Berkan Kadioglu (NEU)
- Basak Celik (NEU)
- Niklas Smedemark-Margulies (NEU)
- Andac Demir (NEU)
- Shaobin Xu (NEU)
All contributions are greatly appreciated!

[![image of contributors generated by https://contributors-img.web.app/ pulling from https://github.com/CAMBI-tech/BciPy/graphs/contributors](https://contrib.rocks/image?repo=CAMBI-tech/BciPy)](https://github.com/CAMBI-tech/BciPy/graphs/contributors)
22 changes: 11 additions & 11 deletions bcipy/acquisition/tests/protocols/lsl/test_lsl_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def test_with_trigger_channel(self):

device.connect()
device.acquisition_init()
self.assertEquals(self.channels, device.channels)
self.assertEqual(self.channels, device.channels)

def test_with_marker_stream(self):
server = LslDataServer(device_spec=self.device_spec, add_markers=True)
Expand All @@ -158,8 +158,8 @@ def test_with_marker_stream(self):

device.connect()
device.acquisition_init()
self.assertEquals(self.channels, device.channels)
self.assertEquals(len(self.channels), len(device.read_data()))
self.assertEqual(self.channels, device.channels)
self.assertEqual(len(self.channels), len(device.read_data()))

def test_with_marker_stream_included(self):
server = LslDataServer(device_spec=self.device_spec, add_markers=True)
Expand All @@ -170,9 +170,9 @@ def test_with_marker_stream_included(self):

device.connect()
device.acquisition_init()
self.assertEquals(self.channels + [MARKER_STREAM_NAME],
device.channels)
self.assertEquals(len(self.channels) + 1, len(device.read_data()))
self.assertEqual(self.channels + [MARKER_STREAM_NAME],
device.channels)
self.assertEqual(len(self.channels) + 1, len(device.read_data()))

def test_with_marker_stream_and_timestamp(self):
server = LslDataServer(device_spec=self.device_spec, add_markers=True)
Expand All @@ -184,9 +184,9 @@ def test_with_marker_stream_and_timestamp(self):

device.connect()
device.acquisition_init()
self.assertEquals(self.channels + [LSL_TIMESTAMP, MARKER_STREAM_NAME],
device.channels)
self.assertEquals(len(self.channels) + 2, len(device.read_data()))
self.assertEqual(self.channels + [LSL_TIMESTAMP, MARKER_STREAM_NAME],
device.channels)
self.assertEqual(len(self.channels) + 2, len(device.read_data()))

def test_renaming_columns(self):
server = LslDataServer(device_spec=self.device_spec,
Expand All @@ -205,8 +205,8 @@ def test_renaming_columns(self):
'C3', 'C4', 'Cz', 'FPz', 'POz', 'CPz', 'O1', 'O2',
'TRG_device_stream', 'TRG'
]
self.assertEquals(expected, device.channels)
self.assertEquals(expected, device.device_info.channels)
self.assertEqual(expected, device.channels)
self.assertEqual(expected, device.device_info.channels)


if __name__ == '__main__':
Expand Down
2 changes: 1 addition & 1 deletion bcipy/helpers/tests/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def tearDown(self):
def test_session_data(self):
"""Test session_data method outputs letters with evidence."""
data = session_data(data_dir=self.data_dir)
self.assertEquals(data["total_number_series"], 2)
self.assertEqual(data["total_number_series"], 2)
self.assertTrue("A" in data["series"]["1"]["0"]["likelihood"])
self.assertTrue("B" in data["series"]["1"]["0"]["likelihood"])

Expand Down
Loading