An easy-to-use platform for EEG experimentation in the classroom
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

patch pyodide

+79 -9
+7 -2
app/epics/pyodideEpics.ts
··· 20 20 plotTestPlot, 21 21 saveEpochs, 22 22 loadPyodide, 23 + loadPatches, 24 + applyPatches, 23 25 loadUtils, 24 26 } from '../utils/pyodide'; 25 27 import { ··· 43 45 tap(() => console.log('launching')), 44 46 mergeMap(loadPyodide), 45 47 tap((worker) => { 46 - console.log('loadPyodide completed, laoding utils'); 47 - // loadUtils(worker); 48 + console.log('loadPyodide completed, loading patches'); 49 + loadPatches(worker); 50 + applyPatches(worker); 51 + console.log('Now loading utils'); 52 + loadUtils(worker); 48 53 }), 49 54 map(PyodideActions.SetPyodideWorker) 50 55 );
+11 -1
app/utils/pyodide/index.ts
··· 14 14 return freshWorker; 15 15 }; 16 16 17 + export const loadPatches = async (worker: Worker) => 18 + worker.postMessage({ 19 + data: readFileSync(path.join(__dirname, '/utils/pyodide/patches.py'), 'utf8'), 20 + }); 21 + 22 + export const applyPatches = async (worker: Worker) => 23 + worker.postMessage({ 24 + data: `apply_patches()`, 25 + }); 26 + 17 27 export const loadUtils = async (worker: Worker) => 18 28 worker.postMessage({ 19 29 data: readFileSync(path.join(__dirname, '/utils/pyodide/utils.py'), 'utf8'), ··· 117 127 } 118 128 // TODO: Figure out how to get image results from pyodide 119 129 return worker.postMessage({ 120 - data: `print('hello world')`, 130 + data: `import matplotlib.pyplot as plt; fig= plt.plot([1,2,3,4])`, 121 131 }); 122 132 }; 123 133
+57
app/utils/pyodide/patches.py
··· 1 + # patch implemented in Pyolite 2 + # https://github.com/jupyterlite/jupyterlite/blob/0d563b9a4cca4b54411229128cb51ac4ba333c8f/packages/pyolite-kernel/py/pyolite/pyolite/patches.py 3 + def patch_matplotlib(): 4 + import os 5 + from io import BytesIO 6 + 7 + # before importing matplotlib 8 + # to avoid the wasm backend (which needs `js.document`, not available in worker) 9 + os.environ["MPLBACKEND"] = "AGG" 10 + 11 + import matplotlib.pyplot 12 + from IPython.display import display 13 + 14 + from .display import Image 15 + 16 + _old_show = matplotlib.pyplot.show 17 + assert _old_show, "matplotlib.pyplot.show" 18 + 19 + def show(): 20 + buf = BytesIO() 21 + matplotlib.pyplot.savefig(buf, format="png") 22 + buf.seek(0) 23 + display(Image(buf.read())) 24 + matplotlib.pyplot.clf() 25 + 26 + matplotlib.pyplot.show = show 27 + 28 + 29 + def patch_pillow(): 30 + import base64 31 + 32 + from PIL import Image as PILImage 33 + 34 + _old_repr_png = PILImage.Image._repr_png_ 35 + assert _old_repr_png 36 + 37 + def _repr_png_(self): 38 + byte = _old_repr_png(self) 39 + return base64.b64encode(byte).decode("utf-8") 40 + 41 + PILImage.Image._repr_png_ = _repr_png_ 42 + 43 + 44 + ALL_PATCHES = [ 45 + patch_pillow, 46 + patch_matplotlib, 47 + ] 48 + 49 + 50 + def apply_patches(): 51 + import warnings 52 + 53 + for patch in ALL_PATCHES: 54 + try: 55 + patch() 56 + except Exception as err: 57 + warnings.warn("faield to apply patch", patch, err)
+2 -4
app/utils/pyodide/utils.py
··· 12 12 find_events, read_epochs, set_eeg_reference, viz) 13 13 from mne.io import RawArray 14 14 from io import StringIO 15 - from mne.channels import read_montage 16 15 17 16 18 17 # plt.style.use(fivethirtyeight) ··· 68 67 69 68 # type of each channels 70 69 ch_types = ['eeg'] * (len(ch_ind) - 1) + ['stim'] 71 - montage = read_montage('standard_1005') 72 70 73 71 # get data and exclude Aux channel 74 72 data = data.values[:, ch_ind].T 75 73 76 74 # create MNE object 77 75 info = create_info(ch_names=ch_names, ch_types=ch_types, 78 - sfreq=sfreq, montage=montage) 79 - raw.append(RawArray(data=data, info=info)) 76 + sfreq=sfreq) 77 + raw.append(RawArray(data=data, info=info).set_montage('standard_1005')) 80 78 81 79 # concatenate all raw objects 82 80 raws = concatenate_raws(raw)
+1 -1
app/utils/pyodide/webworker.js
··· 8 8 9 9 async function loadPyodideAndPackages() { 10 10 self.pyodide = await loadPyodide({ indexURL: './src/pyodide/' }); 11 - await self.pyodide.loadPackage(['numpy']); 11 + await self.pyodide.loadPackage(['matplotlib', 'mne', 'pandas']); 12 12 } 13 13 let pyodideReadyPromise = loadPyodideAndPackages(); 14 14
+1 -1
internals/scripts/InstallPyodide.js
··· 6 6 import url from 'url'; 7 7 import bz2 from 'unbzip2-stream'; 8 8 9 - const PYODIDE_VERSION = '0.17.0'; 9 + const PYODIDE_VERSION = '0.18.0'; 10 10 const TAR_NAME = `pyodide-build-${PYODIDE_VERSION}.tar.bz2`; 11 11 const TAR_URL = `https://github.com/pyodide/pyodide/releases/download/${PYODIDE_VERSION}/pyodide-build-${PYODIDE_VERSION}.tar.bz2`; 12 12 const PYODIDE_DIR = 'app/utils/pyodide/src/';