Skip to content

Commit

Permalink
Upgrade psychopy and add support for python3.9 (#272)
Browse files Browse the repository at this point in the history
* Add cli commands for ease of testing.

Separate requirements based on platform for testing CI. Update IP with new TextBox2 properties.

* Add python3.9 support

* update workflow logic

* change logic to prevent ubuntu issue




log the system


fix syntax error


fix

* fix

* new approach

* new approach

* add attrdict

* update workflow

* Update documentation

* upgrade pandas

* update CHANGELOG
  • Loading branch information
tab-cmd authored Apr 10, 2023
1 parent 73ac0e1 commit 574e7ba
Show file tree
Hide file tree
Showing 14 changed files with 280 additions and 86 deletions.
Binary file not shown.
14 changes: 9 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8]
python-version: [3.8, 3.9]

steps:
- uses: actions/checkout@v2
Expand All @@ -36,6 +36,7 @@ jobs:
sudo apt-get install libsndfile*
sudo apt-get install xvfb
python -m pip install --upgrade pip
pip install attrdict3
pip install -r dev_requirements.txt
pip install -e .
pip install kenlm==0.1 --global-option="--max_order=12"
Expand Down Expand Up @@ -65,19 +66,23 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8]
python-version: [3.8, 3.9]

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 for python3.9
if: matrix.python-version == 3.9
run: |
python -m pip install --upgrade pip
pip install ./.bcipy/downloads/pyWinhook-1.6.2-cp39-cp39-win_amd64.whl
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r dev_requirements.txt
pip install WxPython==4.1.1
pip install -e .
pip install kenlm==0.1 --global-option="--max_order=12"
- name: Lint with flake8
Expand All @@ -95,7 +100,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.7, 3.8]
python-version: [3.8, 3.9]

steps:
- uses: actions/checkout@v2
Expand All @@ -107,7 +112,6 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r dev_requirements.txt
pip install WxPython==4.1.1
pip install -e .
pip install kenlm==0.1 --global-option="--max_order=12"
- name: Lint with flake8
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
- update from `sosfilt` to `sosfiltfilt` #269
- MNE
- convert to mne can now handle conversion to Volts from microvolts, and no channel map #259
- Dependencies
- Upgrade PsychoPy, transformers (#268) and pandas, add support for python3.9, deprecate python3.7 #272
- BciPy client
- Add `-nv` (no visualizations) and `-f` (fake data) client options #272
- Session
- After each session run using `bci_main` an ERP visualization is generated by default using new function `visualize_session_data` #260
- Language Model
Expand Down
40 changes: 25 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,36 @@ Memmott, T., Koçanaoğulları, A., Lawhead, M., Klee, D., Dudy, S., Fried-Oken,

## Dependencies
---------------
This project requires Python 3.7 or 3.8. All other dependencies defined in the requirements.txt.
This project requires Python 3.8 or 3.9. Please see notes below for additional OS specific dependencies before installation can be completed.

### Linux

You will need to install the prerequisites defined in `scripts\shell\linux_requirements.sh` as well as `pip install attrdict3`.

### Windows

If you are using a Windows machine, you will need to install the [Microsoft Visual C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/).

*python 3.9 only!*
You will need to install pyWinhook manually. See [here](https://www.lfd.uci.edu/~gohlke/pythonlibs/#pywinhook) for the appropriate wheel file (`pyWinhook‑1.6.2‑cp39‑cp39‑win_amd64.whl`). Then run `pip install <path_to_wheel_file>`. We also include the 64-bit wheel file in the `.bcipy/downloads/` directory.

### Mac

If you are using a Mac, you will need to install XCode and enable command line tools. `xcode-select --install`.

## Installation
---------------

#### BciPy Setup

In order to run BciPy on your computer, first install **Python 3** [from here.](https://www.python.org/downloads/)
In order to run BciPy on your computer, after following the dependencies above, you will need to install the BciPy package.

To use all the goodies locally (including the GUI and demo scripts)
To install for use locally,
1. Git clone https://github.com/BciPy/BciPy.git
2. Change directory in your terminal to the repo
3. Run `pip install -e .`
4. If using Mac, you will need to install XCode and enable command line tools. `xcode-select --install`
5. If you're on Windows, you may need to uninstall pygame (`pip uninstall pygame`). Psychopy, for historical reasons, keeps pygame but it just spams your console logs if you only want to use pyglet (which we use in this repository!)
6. To use the KenLMLanguageModel class, you must manually install the kenlm package. `pip install kenlm==0.1 --global-option="--max_order=12"`.
4. To use the KenLMLanguageModel class, you must manually install the kenlm package. `pip install kenlm==0.1 --global-option="--max_order=12"`.


If wanting the latest version from PyPi:
1. `pip install bcipy`
Expand All @@ -48,15 +61,12 @@ make dev-install

#### 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.

Ex. `bcipy` *this will use default parameters, user, experiment and task*

You can pass it attributes with flags, if desired.

Ex. `bcipy --user "bci_user" --task "RSVP Calibration"`

Use the help flag to see other available input options: `bcipy --help`
Two ways to get started using BciPy for data collection:
1. Run `python bcipy/gui/BCInterface.py` in your command prompt or terminal from from base BciPy directory. This will execute the main BCI GUI. You may also use the command `make bci-gui`.
2. Invoke the experiment directly using command line utility `bcipy`.
- You can pass it attributes with flags, if desired.
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

Expand Down
14 changes: 4 additions & 10 deletions bcipy/display/paradigm/rsvp/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,21 +287,16 @@ def _generate_inquiry_preview(self) -> visual.TextBox2:
Using the self.stimuli_inquiry list, construct a preview box to display to the user. This method
assumes the presence of a fixation (+).
"""
if not self.full_screen:
reduce_factor = 4.85
wrap_width = 1.1
else:
reduce_factor = 4.75
wrap_width = .9
text = ' '.join(self.stimuli_inquiry).split('+ ')[1]

return self._create_stimulus(
self.stimuli_height / reduce_factor,
0.12,
stimulus=text,
units='height',
stimuli_position=self.stimuli_pos,
mode='textbox',
wrap_width=wrap_width)
align_text='left',
wrap_width=0.025)

def _generate_inquiry(self) -> list:
"""Generate inquiry.
Expand Down Expand Up @@ -425,7 +420,7 @@ def _create_stimulus(
border=False):
"""Create Stimulus.
Returns a TextStim or ImageStim object.
Returns a TextStim, ImageStim or TextBox object.
"""
if not stimuli_position:
stimuli_position = self.stimuli_pos
Expand Down Expand Up @@ -465,6 +460,5 @@ def _create_stimulus(
letterHeight=height,
size=[.5, .5],
pos=stimuli_position,
anchor=align_text,
alignment=align_text,
)
1 change: 1 addition & 0 deletions bcipy/display/tests/paradigm/rsvp/test_rsvp_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def test_preview_inquiry_generate_inquiry_preview_fixation(self):
units='height',
stimuli_position=self.rsvp.stimuli_pos,
mode='textbox',
align_text='left',
wrap_width=any()
).thenReturn(stim_mock)

Expand Down
2 changes: 1 addition & 1 deletion bcipy/display/tests/test_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


class TestInitializeDisplayWindow(unittest.TestCase):
"""This is Test Case for Initialzing Display Window."""
"""This is Test Case for Initializing Display Window."""

def setUp(self):
"""Set up needed items for test."""
Expand Down
4 changes: 2 additions & 2 deletions bcipy/helpers/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from bcipy.gui.alert import confirm


def validate_bcipy_session(parameters: dict) -> bool:
def validate_bcipy_session(parameters: dict, fake_data: bool) -> bool:
"""Check pre-conditions for a BciPy session. If any possible problems are
detected, alert the user and prompt to continue.
Expand All @@ -26,7 +26,7 @@ def validate_bcipy_session(parameters: dict) -> bool:
-------
True if it's okay to continue, otherwise False
"""
possible_alerts = [(parameters['fake_data'], '* Fake data is on.'),
possible_alerts = [(fake_data, '* Fake data is on.'),
(is_connected(), '* Internet is on.'),
(is_battery_powered(), '* Operating on battery power')]
alert_messages = [
Expand Down
37 changes: 28 additions & 9 deletions bcipy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ def bci_main(
task: TaskType,
experiment: str = DEFAULT_EXPERIMENT_ID,
alert: bool = False,
visualize: bool = True) -> bool:
visualize: bool = True,
fake: bool = False) -> bool:
"""BCI Main.
The BCI main function will initialize a save folder, construct needed information
Expand All @@ -53,12 +54,17 @@ def bci_main(
experiment_id (str): Name of the experiment. Default name is DEFAULT_EXPERIMENT_ID.
alert (bool): whether to alert the user when the task is complete
visualize (bool): whether to visualize data at the end of a task
fake (bool): whether to use fake acquisition data during the session. If None, the
fake data will be determined by the parameters file.
"""
validate_experiment(experiment)
# Load parameters
parameters = load_json_parameters(parameter_location, value_cast=True)

if not validate_bcipy_session(parameters):
# cli overrides parameters file for fake data if provided
fake = fake if fake is True else parameters['fake_data']

if not validate_bcipy_session(parameters, fake):
return False

# Update property to reflect the parameter source
Expand Down Expand Up @@ -91,7 +97,7 @@ def bci_main(
# Collect experiment field data
collect_experiment_field_data(experiment, save_folder)

if execute_task(task, parameters, save_folder, alert):
if execute_task(task, parameters, save_folder, alert, fake):
if visualize:
visualize_session_data(save_folder, parameters)
return True
Expand All @@ -103,7 +109,8 @@ def execute_task(
task: TaskType,
parameters: dict,
save_folder: str,
alert: bool) -> bool:
alert: bool,
fake: bool) -> bool:
"""Execute Task.
Executes the desired task by setting up the display window and
Expand All @@ -115,15 +122,14 @@ def execute_task(
parameters (dict): parameter dictionary
save_folder (str): path to save folder
alert (bool): whether to alert the user when the task is complete
fake (bool): whether to use fake acquisition data during the session
Returns:
(bool): True if the task was successfully executed, False otherwise
"""
signal_model = None
language_model = None

fake = parameters['fake_data']

# Init EEG Model, if needed. Calibration Tasks Don't require probabilistic
# modules to be loaded.
if task not in TaskType.calibration_tasks():
Expand Down Expand Up @@ -202,7 +208,7 @@ def _clean_up_session(
def bcipy_main() -> None:
"""BciPy Main.
Command line interface used for running a registered experiment task in Bcipy. To see what
Command line interface used for running a registered experiment task in BciPy. To see what
is available use the --help flag.
"""
# Needed for windows machines
Expand All @@ -228,11 +234,24 @@ def bcipy_main() -> None:
'--alert',
default=False,
action='store_true',
help='Alert the user when the task is complete.')
help='Alert the user when the session is complete.')
parser.add_argument(
'-nv',
'--noviz',
default=True,
action='store_false',
help='Suppress visuals of the data after the session is complete.')
parser.add_argument(
'-f',
'--fake',
default=False,
action='store_true',
help='Use fake acquisition data for testing.')
args = parser.parse_args()

# Start BCI Main
bci_main(args.parameters, str(args.user), TaskType.by_value(str(args.task)), str(args.experiment), args.alert)
bci_main(args.parameters, str(args.user), TaskType.by_value(str(args.task)),
str(args.experiment), args.alert, args.noviz, args.fake)


if __name__ == '__main__':
Expand Down
Loading

0 comments on commit 574e7ba

Please sign in to comment.