Skip to content

Commit

Permalink
Merge pull request kylemath#138 from kylemath/bandsLesson
Browse files Browse the repository at this point in the history
Bands lesson
  • Loading branch information
kylemath authored Feb 24, 2020
2 parents 9c778f4 + 7ad9880 commit 5d5286f
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useCallback } from "react";
import { catchError, multicast } from "rxjs/operators";

import { Card, Stack, TextContainer, RangeSlider, Select} from "@shopify/polaris";
import { Card, Stack, TextContainer, RangeSlider, Select, Link} from "@shopify/polaris";
import { Subject } from "rxjs";

import { zipSamples } from "muse-js";
Expand Down Expand Up @@ -103,12 +103,12 @@ export function setup(setData, Settings) {
export function renderModule(channels) {
function RenderCharts() {

const bands = 'bands';
const tone = 'tone';
const cube = 'cube';
const flock = 'flock';
const draw = 'draw';
const flock3d = 'flock3d';
const bands = '3D Frequency Bands';
const tone = 'Play simple music with your frequency bands';
const cube = 'Control a Cube with your Alpha Power';
const flock = 'Control a Flock with Alpha and Beta';
const draw = 'Draw a picture with Alpha and Beta';
const flock3d = 'Control a 3d Flock with Alpha, Beta, and Theta';

const chartTypes = [
{ label: bands, value: bands },
Expand Down Expand Up @@ -201,6 +201,25 @@ export function renderModule(channels) {
<TextContainer>
<p>{specificTranslations.description}</p>
</TextContainer>
<img
src={ require("./electrodediagram2.png")}
alt="F7Electrode"
width="25%"
height="auto"
></img>
<Link url="https://p5js.org/learn/interactivity.html"
external={true}>
Link to learn more about making your own easy P5.js animations </Link>
<br />
<Link url="https://p5js.org/examples/"
external={true}>
Examples of other P5.js animations to get started </Link>
<TextContainer>
<p>{[
"We are working on allowing for people to make their own animations with a p5.js editor. ",
"For now if you want us to make a new one make a github issue with your p5.js animation and describe your idea"
]}</p>
</TextContainer>
</Stack>
</Card.Section>
<Card.Section>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"title": "P5js integration",
"description": [
"In the next demo we look at the traditional frequency bands. ",
"This time instead of graphing them we pipe them into a live web animation."
],
"xlabel": "Frequency (Hz)",
"ylabel": "Power (\u03BCV\u00B2)"
"This time instead of graphing them we pipe them into a live web animation. ",
"For simplicity for now we will only use the left frontal electrode AF7. ",
"All of these animations are embedded p5js animations."
]
}
118 changes: 114 additions & 4 deletions src/components/PageSwitcher/components/EEGEduBands/EEGEduBands.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { catchError, multicast } from "rxjs/operators";

import { TextContainer, Card, Stack, RangeSlider, Button, ButtonGroup, Modal } from "@shopify/polaris";
import { TextContainer, Card, Stack, RangeSlider, Button, ButtonGroup, Modal, Link } from "@shopify/polaris";
import { saveAs } from 'file-saver';
import { takeUntil } from "rxjs/operators";
import { Subject, timer } from "rxjs";
Expand All @@ -27,7 +27,7 @@ import { bandLabels } from "../../utils/chartUtils";
export function getSettings () {
return {
cutOffLow: 2,
cutOffHigh: 20,
cutOffHigh: 50,
interval: 100,
bins: 256,
duration: 1024,
Expand Down Expand Up @@ -119,7 +119,6 @@ export function renderModule(channels) {
labelString: specificTranslations.ylabel
},
ticks: {
max: 25,
min: 0
}
}
Expand All @@ -146,9 +145,75 @@ export function renderModule(channels) {
<Card title={specificTranslations.title}>
<Card.Section>
<Stack>
<TextContainer>
<p>{[
"In the next demo we look at the traditional frequency bands. ",
"Oscillations in the brain are important as a mechinasm of brain function and communication. ",
"For example, within a brain area, cellular firing becomes locked to the ongoing oscillations of the local field potential: "
]}</p>
</TextContainer>
<img
src={ require("./phaseLockedFiring.png")}
alt="phaseLocked"
width="50%"
height="auto"
></img>
</Stack>
<Stack>
<Link url="hhttps://en.wikipedia.org/wiki/Neural_oscillation#/media/File:SimulationNeuralOscillations.png"
external={true}>
Image Source - Wikipedia </Link>
<br />
<TextContainer>
<p>{[
"Since oscillations can control the timing of neural firing, they can also be used to communciate information and create distributed representations. ",
"Two nearby brain regions that oscillate in sync will have cells that also fire in sync, which also means the neurons they connect to will be more influenced. ",
"Different brain regions have different frequency oscillations at different times "
]}</p>
</TextContainer>
<TextContainer>
<p>{specificTranslations.description}</p>
<p>{[
"Oscillations in the brain seem to belong to a number of basic families or frequency bands that are influenced by cognition in different ways. ",
"We take the same spectra that was computed in Spectra and divide into five bands. ",
"Delta (1-4 Hz), Theta (4-7 Hz), Alpha (7-12 Hz), Beta (12-30 Hz), and Gamma (30+ Hz). "
]}</p>
</TextContainer>
<img
src={ require("./freqBands.jpg")}
alt="freqBands"
width="50%"
height="auto"
></img>
</Stack>
<Stack>
<Link url="https://upload.wikimedia.org/wikipedia/commons/5/59/Analyse_spectrale_d%27un_EEG.jpg"
external={true}>
Image Source - Wikipedia </Link>
<br />

<TextContainer>
<p>{[
"These different frequency bands are associated with different brain states. ",
"For example, when we pay focus attention to something, our alpha goes down and our beta oscillations increase. ",
"Gamma oscillations are associated with neural activity, but for the most part Gamma oscillations are very difficult to measure outside the head (very small) and so we will ignore them. ",
"Theta oscillations increase during spatial navigation and are associated with learning and memory. ",
"Alpha oscillations are assocaited with attention and active inhbition of neural activity, we will consider them further below. "
]}</p>
</TextContainer>


</Stack>
</Card.Section>
<Card.Section>
<Stack>

<TextContainer>
<p>{[
"Connect a muse and watch the following bar charts of the frequency band power. There is one chart for each electrode. ",
"See if you can pick one of the bars and try to control its height by relaxing."
]}</p>
</TextContainer>

</Stack>
</Card.Section>
<Card.Section>
Expand All @@ -158,6 +223,11 @@ export function renderModule(channels) {
);
}


// https://en.wikipedia.org/wiki/Neural_oscillation#/media/File:SimulationNeuralOscillations.png
// https://upload.wikimedia.org/wikipedia/commons/5/59/Analyse_spectrale_d%27un_EEG.jpg
//

export function renderSliders(setData, setSettings, status, Settings) {

function resetPipeSetup(value) {
Expand Down Expand Up @@ -228,6 +298,46 @@ export function renderRecord(recordPopChange, recordPop, status, Settings, setSe
return (
<Card title={'Record Data'} sectioned>
<Stack>
<TextContainer>
<p>{[
"One of the earliest and easiest to measure changes in the EEG is that of alpha oscillations when the eyes closed. ",
"We will test these changes by recording data in two conditions, and comparing the average alpha at all four electrodes between conditions. ",
"We expect to replicate the following relationship: "
]}</p>
</TextContainer>
<img
src={ require("./alphaOpenClosed.png")}
alt="closedOpen"
width="50%"
height="auto"
></img>
</Stack>
<Stack>
<Link url="https://www.semanticscholar.org/paper/Coupling-between-visual-alpha-oscillations-and-mode-Mo-Liu/82593c9b9662d4dc022d51607b313f851f670246"
external={true}>
Image Source - Mo et al., 2013, Neuroimage </Link>
<br />
<br />
<br />

<TextContainer>
<p>{[
"First go to the Raw module 3 and check the data and connection quality. ",
"Then come back to Module 6, no need to change any settings. ",
"We will record two sessions for each person in your group, one with eyes open and one with eyes closed. ",
"Once recorded you can open the .csv file and observe what gets saved. Along the rows are the different frequency bands from each electrode, we are going to average over all four electrodes in this assignment. ",
"We are also going to average over time, which is shown on different rows. ",
"So please compute the average ALPHA power in that output file, and do the same for the other condition, make sure to keep track of which file was created during which condition. ",
"Compare your values for eyes open vs eyes closed, did you find the expected difference? ",
"Why do you think alpha differs when we close our eyes? "
]}</p>
</TextContainer>
<TextContainer>
<p>{[
"Once you are complete, move on to the next Module and control live animations with the values of these frequency bands. ",
]}</p>
</TextContainer>

<RangeSlider
disabled={status === generalTranslations.connect}
min={2}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
{
"title": "Frequency Bands Data",
"description": [
"In the next demo we look at the traditional frequency bands. ",
"We take the same spectra that was computed in Spectra and divide into four bands. ",
"Delta (1-4 Hz), Theta (4-7 Hz), Alpha (7-12 Hz), Beta (12-30 Hz), and Gamme (30+ Hz). ",
"See if you can pick one of the bars and try to control its height by relaxing."
],
"xlabel": "Frequency (Hz)",
"ylabel": "Power (\u03BCV\u00B2)"
}
14 changes: 7 additions & 7 deletions src/components/PageSwitcher/components/EEGEduRaw/EEGEduRaw.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { chartStyles, generalOptions } from "../chartOptions";
import * as generalTranslations from "../translations/en";
import * as specificTranslations from "./translations/en";

import { generateXTics, standardDeviation } from "../../utils/chartUtils";
import { generateXTics } from "../../utils/chartUtils";

export function getSettings () {
return {
Expand Down Expand Up @@ -71,7 +71,7 @@ export function setup(setData, Settings) {
Object.values(rawData).forEach((channel, index) => {
channel.datasets[0].data = data.data[index];
channel.xLabels = generateXTics(Settings.srate, Settings.duration);
channel.datasets[0].qual = standardDeviation(data.data[index])
// channel.datasets[0].qual = standardDeviation(data.data[index])
});

return {
Expand Down Expand Up @@ -127,27 +127,27 @@ export function renderModule(channels) {
const newData = {
datasets: [{
label: channelNames[0],
borderColor: 'rgba(217,95,2, ' + Math.max(0.2,(2-channels.data.ch0.datasets[0].qual/200)) + ')',
borderColor: 'rgba(217,95,2)',
data: channels.data.ch0.datasets[0].data.map(function(x) {return x + 300}),
fill: false
}, {
label: channelNames[1],
borderColor: 'rgba(27,158,119, ' + Math.max(0.2,(2-channels.data.ch1.datasets[0].qual/200)) + ')',
borderColor: 'rgba(27,158,119)',
data: channels.data.ch1.datasets[0].data.map(function(x) {return x + 200}),
fill: false
}, {
label: channelNames[2],
borderColor: 'rgba(117,112,179, ' + Math.max(0.2,(2-channels.data.ch2.datasets[0].qual/200)) + ')',
borderColor: 'rgba(117,112,179)',
data: channels.data.ch2.datasets[0].data.map(function(x) {return x + 100}),
fill: false
}, {
label: channelNames[3],
borderColor: 'rgba(231,41,138, ' + Math.max(0.2,(2-channels.data.ch3.datasets[0].qual/200)) + ')',
borderColor: 'rgba(231,41,138)',
data: channels.data.ch3.datasets[0].data.map(function(x) {return x + 0}),
fill: false
}, {
label: channelNames[4],
borderColor: 'rgba(20,20,20, ' + Math.max(0.2,(2-channels.data.ch4.datasets[0].qual/200)) + ')',
borderColor: 'rgba(20,20,20)',
data: channels.data.ch4.datasets[0].data.map(function(x) {return x + -100}),
fill: false
}],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,27 +148,27 @@ export function renderModule(channels) {
datasets: [{
label: channelNames[0],
borderColor: 'rgba(217,95,2)',
data: channels.data.ch0.datasets[0].data.map(function(x) {return x * -1}),
data: channels.data.ch0.datasets[0].data,
fill: false
}, {
label: channelNames[1],
borderColor: 'rgba(27,158,119)',
data: channels.data.ch1.datasets[0].data.map(function(x) {return x * -1}),
data: channels.data.ch1.datasets[0].data,
fill: false
}, {
label: channelNames[2],
borderColor: 'rgba(117,112,179)',
data: channels.data.ch2.datasets[0].data.map(function(x) {return x + 0}),
data: channels.data.ch2.datasets[0].data,
fill: false
}, {
label: channelNames[3],
borderColor: 'rgba(231,41,138)',
data: channels.data.ch3.datasets[0].data.map(function(x) {return x + 0}),
data: channels.data.ch3.datasets[0].data,
fill: false
}, {
label: channelNames[4],
borderColor: 'rgba(20,20,20)',
data: channels.data.ch4.datasets[0].data.map(function(x) {return x + 0}),
data: channels.data.ch4.datasets[0].data,
fill: false
}],
xLabels: channels.data.ch0.xLabels
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import P5Wrapper from 'react-p5-wrapper';

export function getSettings () {
return {
cutOffLow: 1,
cutOffHigh: 100,
cutOffLow: 2,
cutOffHigh: 50,
interval: 16,
bins: 128,
duration: 128,
Expand Down Expand Up @@ -102,14 +102,16 @@ export function renderModule(channels) {
}

//only left frontal channel
if (index === 1) {
if (index === 1 && window.freqs) {
return (
<React.Fragment key={'dum'}>
<Card.Section>
{window.freqs.slice(-1)[0] + ' Hz'}
<P5Wrapper sketch={sketchSpectro}
psd={window.psd}
bins={window.bins}
/>
/>
{window.freqs[0] + ' Hz'}
</Card.Section>
</React.Fragment>
);
Expand All @@ -127,6 +129,12 @@ export function renderModule(channels) {
<TextContainer>
<p>{specificTranslations.description}</p>
</TextContainer>
<img
src={ require("./electrodediagram2.png")}
alt="F7Electrode"
width="25%"
height="auto"
></img>
</Stack>
</Card.Section>
<Card.Section>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default function sketchSpectro (p) {
value = spectrum[i];

let c = (value/5)*255;
p.fill(255-c, 255-c, 255-c);
p.fill(c, c, c);
let percent = i / binCount;
let y = percent * p.height;
p.rect(p.width - speed, p.height - y, speed, p.height / binCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
"description": [
"Back to the full spectra, we can also look at how this changes over time in a single image. ",
"This image, with time on the horizontal x-axis and freqency on the vertical y-axis is like a heat map or topographic map. ",
"Darker regions represent frequencies and times with larger power. ",
"Remember that on the spectra power is the vertical dimension, here is the is the colour."
],
"xlabel": "Time (ms)",
"ylabel": "Frequency (Hz)",
"zlabel": "Power (\u03BCV\u00B2)"
"The most recent data is on the right side",
"Lighter regions are frequencies with larger power. ",
"Remember that on the frequency spectra power is the vertical dimension, here on the spectrogram the height of that line is shown as the lightness.",
"This plot is showing only data from the left frontal electrode AF7"
]
}

0 comments on commit 5d5286f

Please sign in to comment.