Skip to content

Commit 6e7a59f

Browse files
authored
Merge pull request #167 from NeuroTechX/fix-ci
2 parents 60482df + 430bafb commit 6e7a59f

10 files changed

Lines changed: 135 additions & 389 deletions

File tree

.github/workflows/docs.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88

99
jobs:
1010
build:
11-
runs-on: ubuntu-18.04
11+
runs-on: ubuntu-latest
1212
steps:
1313
- uses: actions/checkout@v2
1414
- name: Set up Python
@@ -17,16 +17,14 @@ jobs:
1717
python-version: 3.8
1818
- name: Install dependencies
1919
run: |
20+
make install-deps-apt
2021
python -m pip install --upgrade pip wheel
2122
22-
# Install wxPython wheels since they are distribution-specific and therefore not on PyPI
23-
# See: https://wxpython.org/pages/downloads/index.html
24-
pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 wxPython
25-
23+
make install-deps-wxpython
2624
pip install .
2725
- name: Build docs
2826
run: |
29-
cd doc && make html
27+
make docs
3028
- name: Deploy Docs
3129
uses: peaceiris/actions-gh-pages@v3
3230
if: github.ref == 'refs/heads/master'

.github/workflows/test.yml

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@ on:
88

99
jobs:
1010
test:
11-
name: ${{ matrix.os }}, py-${{ matrix.python_version }}
11+
name: test (${{ matrix.os }}, py-${{ matrix.python_version }})
1212
runs-on: ${{ matrix.os }}
1313
strategy:
1414
fail-fast: false
1515
matrix:
1616
os: [ubuntu-latest, windows-latest, macOS-latest]
17-
python_version: [3.7]
17+
python_version: [3.8]
1818
include:
1919
- os: ubuntu-latest
20-
python_version: 3.8
20+
python_version: 3.9
21+
#- os: macOS-latest
22+
# python_version: 3.9
2123
# Experimental: Python 3.9
2224
# See issue: https://github.com/NeuroTechX/eeg-notebooks/issues/50
2325
#- os: ubuntu-18.04
@@ -39,33 +41,22 @@ jobs:
3941
- name: Install APT dependencies
4042
if: "startsWith(runner.os, 'Linux')"
4143
run: |
42-
# update archive links
43-
sudo apt-get update
44-
# xvfb is a dependency to create a virtual display
45-
# libgtk-3-dev is a requirement for wxPython
46-
# freeglut3-dev is a requirement for a wxPython dependency
47-
sudo apt-get -y install xvfb libgtk-3-dev freeglut3-dev
44+
make install-deps-apt
45+
- name: Upgrade pip
46+
run: |
47+
python -m pip install --upgrade pip wheel
4848
- name: Install Linux dependencies
4949
if: "startsWith(runner.os, 'Linux')"
5050
run: |
51-
python -m pip install --upgrade pip wheel
52-
53-
# Install wxPython wheels since they are distribution-specific and therefore not on PyPI
54-
# See: https://wxpython.org/pages/downloads/index.html
55-
pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 wxPython
56-
57-
pip install .
58-
- name: Install MacOS/Windows dependencies
51+
make install-deps-wxpython
52+
- name: Install dependencies
5953
run: |
60-
python -m pip install --upgrade pip wheel
61-
pip install .
54+
make build
6255
- name: Run eegnb install test
6356
shell: bash
64-
pip install -U psychtoolbox # JG_ADD
6557
run: |
6658
if [ "$RUNNER_OS" == "Linux" ]; then
6759
Xvfb :0 -screen 0 1024x768x24 -ac +extension GLX +render -noreset &> xvfb.log &
68-
/
6960
export DISPLAY=:0
7061
fi
7162
eegnb --help
@@ -77,9 +68,10 @@ jobs:
7768
Xvfb :0 -screen 0 1024x768x24 -ac +extension GLX +render -noreset &> xvfb.log &
7869
export DISPLAY=:0
7970
fi
80-
pytest
71+
make test
8172
8273
typecheck:
74+
name: typecheck (${{ matrix.os }}, py-${{ matrix.python_version }})
8375
runs-on: ${{ matrix.os }}
8476
strategy:
8577
fail-fast: false
@@ -96,27 +88,17 @@ jobs:
9688
- name: Install APT dependencies
9789
if: "startsWith(runner.os, 'Linux')"
9890
run: |
99-
# update archive links
100-
sudo apt-get update
101-
# xvfb is a dependency to create a virtual display
102-
# libgtk-3-dev is a requirement for wxPython
103-
# freeglut3-dev is a requirement for a wxPython dependency
104-
sudo apt-get -y install xvfb libgtk-3-dev freeglut3-dev
91+
make install-deps-apt
92+
- name: Upgrade pip
93+
run: |
94+
python -m pip install --upgrade pip wheel
10595
- name: Install Linux dependencies
10696
if: "startsWith(runner.os, 'Linux')"
10797
run: |
108-
python -m pip install --upgrade pip wheel
109-
110-
# Install wxPython wheels since they are distribution-specific and therefore not on PyPI
111-
# See: https://wxpython.org/pages/downloads/index.html
112-
pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 wxPython
113-
114-
pip install .
115-
- name: Install MacOS/Windows dependencies
98+
make install-deps-wxpython
99+
- name: Install dependencies
116100
run: |
117-
python -m pip install --upgrade pip wheel
118-
pip install .
101+
make build
119102
- name: Typecheck
120103
run: |
121-
# Exclude visual_cueing due to errors
122-
python -m mypy --exclude 'examples/visual_cueing'
104+
make typecheck

Makefile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
build:
2+
pip install .
3+
4+
test:
5+
pytest
6+
7+
typecheck:
8+
# Exclude visual_cueing due to errors
9+
python -m mypy --exclude 'examples/visual_cueing'
10+
11+
docs:
12+
cd doc && make html
13+
14+
clean:
15+
cd doc && make clean
16+
17+
install-deps-apt:
18+
sudo apt-get update # update archive links
19+
20+
# xvfb is a dependency to create a virtual display
21+
# libgtk-3-dev is a requirement for wxPython
22+
# freeglut3-dev is a requirement for a wxPython dependency
23+
# portaudio19-dev *might* be required to import psychopy on Ubuntu
24+
# pulseaudio *might* be required to actually run the tests (on PsychoPy import)
25+
# libpulse-dev required to build pocketsphinx (speech recognition dependency of psychopy)
26+
# libsdl2-dev required by psychopy
27+
sudo apt-get -y install xvfb libgtk-3-dev freeglut3-dev portaudio19-dev libpulse-dev pulseaudio libsdl2-dev
28+
29+
install-deps-wxpython:
30+
# Install wxPython wheels since they are distribution-specific and therefore not on PyPI
31+
# See: https://wxpython.org/pages/downloads/index.html
32+
pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 wxPython

doc/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def setup(app):
263263
'backreferences_dir': 'generated', # Where to drop linking files between examples & API
264264
'doc_module': ('eeg-notebooks'),
265265
'reference_url': {'eeg-notebooks': None},
266-
'remove_conffig_comments': True}
266+
'remove_config_comments': True}
267267

268268
"""
269269
sphinx_gallery_conf = {
@@ -284,7 +284,7 @@ def setup(app):
284284
'backreferences_dir': 'generated', # Where to drop linking files between examples & API
285285
'doc_module': ('eeg-notebooks',),
286286
'reference_url': {'eeg-notebooksS': None},
287-
'remove_conffig_comments': True,
287+
'remove_config_comments': True,
288288
}
289289
290290
"""

eegnb/analysis/utils.py

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
from copy import deepcopy
33
import math
44
import logging
5+
import sys
56
from collections import OrderedDict
67
from glob import glob
7-
from typing import Union, List, Dict
8+
from typing import Union, List
89
from time import sleep, time
9-
from numpy.core.fromnumeric import std
1010

1111
import pandas as pd
1212
import numpy as np
@@ -16,13 +16,13 @@
1616
from mne.channels import make_standard_montage
1717
from mne.filter import create_filter
1818
from matplotlib import pyplot as plt
19+
from scipy import stats
1920
from scipy.signal import lfilter, lfilter_zi
2021

2122
from eegnb import _get_recording_dir
2223
from eegnb.devices.eeg import EEG
2324
from eegnb.devices.utils import EEG_INDICES, SAMPLE_FREQS
2425

25-
2626

2727
# this should probably not be done here
2828
sns.set_context("talk")
@@ -32,6 +32,33 @@
3232
logger = logging.getLogger(__name__)
3333

3434

35+
def _bootstrap(data, n_boot: int, ci: float):
36+
"""From: https://stackoverflow.com/a/47582329/965332"""
37+
boot_dist = []
38+
for i in range(int(n_boot)):
39+
resampler = np.random.randint(0, data.shape[0], data.shape[0])
40+
sample = data.take(resampler, axis=0)
41+
boot_dist.append(np.mean(sample, axis=0))
42+
b = np.array(boot_dist)
43+
s1 = np.apply_along_axis(stats.scoreatpercentile, 0, b, 50 - ci / 2)
44+
s2 = np.apply_along_axis(stats.scoreatpercentile, 0, b, 50 + ci / 2)
45+
return (s1, s2)
46+
47+
48+
def _tsplotboot(ax, data, time: list, n_boot: int, ci: float, color):
49+
"""From: https://stackoverflow.com/a/47582329/965332"""
50+
# Time forms the xaxis of the plot
51+
if time is None:
52+
x = np.arange(data.shape[1])
53+
else:
54+
x = np.asarray(time)
55+
est = np.mean(data, axis=0)
56+
cis = _bootstrap(data, n_boot, ci)
57+
ax.fill_between(x, cis[0], cis[1], alpha=0.2, color=color)
58+
ax.plot(x, est, color=color)
59+
ax.margins(x=0)
60+
61+
3562
def load_csv_as_raw(
3663
fnames: List[str],
3764
sfreq: float,
@@ -152,7 +179,9 @@ def load_data(
152179
site = "*"
153180

154181
data_path = (
155-
_get_recording_dir(device_name, experiment, subject_str, session_str, site, data_dir)
182+
_get_recording_dir(
183+
device_name, experiment, subject_str, session_str, site, data_dir
184+
)
156185
/ "*.csv"
157186
)
158187
fnames = glob(str(data_path))
@@ -193,7 +222,8 @@ def plot_conditions(
193222
ylim=(-6, 6),
194223
diff_waveform=(1, 2),
195224
channel_count=4,
196-
channel_order=None):
225+
channel_order=None,
226+
):
197227
"""Plot ERP conditions.
198228
Args:
199229
epochs (mne.epochs): EEG epochs
@@ -219,10 +249,9 @@ def plot_conditions(
219249
"""
220250

221251
if channel_order:
222-
channel_order = np.array(channel_order)
252+
channel_order = np.array(channel_order)
223253
else:
224-
channel_order = np.array(range(channel_count))
225-
254+
channel_order = np.array(range(channel_count))
226255

227256
if isinstance(conditions, dict):
228257
conditions = OrderedDict(conditions)
@@ -232,7 +261,7 @@ def plot_conditions(
232261

233262
X = epochs.get_data() * 1e6
234263

235-
X = X[:,channel_order]
264+
X = X[:, channel_order]
236265

237266
times = epochs.times
238267
y = pd.Series(epochs.events[:, -1])
@@ -249,13 +278,15 @@ def plot_conditions(
249278

250279
for ch in range(channel_count):
251280
for cond, color in zip(conditions.values(), palette):
252-
sns.tsplot(
253-
X[y.isin(cond), ch],
281+
y_cond = y.isin(cond)
282+
X_cond = X[y_cond, ch]
283+
_tsplotboot(
284+
ax=axes[ch],
285+
data=X_cond,
254286
time=times,
255287
color=color,
256288
n_boot=n_boot,
257289
ci=ci,
258-
ax=axes[ch],
259290
)
260291

261292
if diff_waveform:

0 commit comments

Comments
 (0)