created oddball task, response markers for red circle spacebar or tap screen

Esse commit está contido em:
Kyle Mathewson
2020-01-05 20:57:38 -07:00
commit 1c00ac0805
3 arquivos alterados com 72 adições e 19 exclusões
@@ -5,7 +5,7 @@ import { Subject } from "rxjs";
import { TextContainer, Card, Stack, RangeSlider, Button, ButtonGroup, Modal } from "@shopify/polaris";
import { saveAs } from 'file-saver';
import { take } from "rxjs/operators";
import { zipSamples } from "muse-js";
@@ -174,14 +174,27 @@ export function renderSliders(setData, setSettings, status, Settings) {
export function renderRecord(recordPopChange, recordPop, status, Settings) {
return (
<Card title={'Record ' + Settings.name + ' Data'} sectioned>
<Card title={'Run ERP experiment'} sectioned>
<Card.Section>
<p>
{"When you are recording Evoked data it is recommended you set the "}
{"number of sampling points between epochs onsets to be equal to the epoch duration. "}
{"This will ensure that consecutive rows of your output file are not overlapping in time."}
{"It will make the live plots appear more choppy."}
</p>
{"Clicking this button will begin the experiment so check your data quality on the raw module first. "}
{"A window will pop up when you click the button and a series of circles will appear. Stare at the cross in the center. "}
{"There will be red and blue circles, ignore the blue ones."}
{"Whenever you see a red circle, as fast as you can either press spacebar on a keyboard, or tap the touchscreen on a tablet or phone. "}
{"This entire time the eeg data will be saved along with a column indicating which target was on the screen, and another for the responses. "}
{"The task will continue for a few minutes and once it is finished a .csv file will automatically download. "}
{"This .csv file has a row for each time point, a column for each electrode, and the columns indicating when targets appeared, and when responses were made. "}
{"It saves a marker of 20 when the target is on, a marker of 10 when the blue standards are on, and a peak when the spacebar or touchscreen are pressed, here you can see those synced with an eeg channel: "}
</p>
<p>
<img
src={ require("./dataExample.png")}
alt="dataExample"
width="100%"
height="auto"
></img>
</p>
</Card.Section>
<Stack>
<ButtonGroup>
@@ -193,14 +206,14 @@ export function renderRecord(recordPopChange, recordPop, status, Settings) {
primary={status !== generalTranslations.connect}
disabled={status === generalTranslations.connect}
>
{'Save to CSV'}
{'Run oddball experiment'}
</Button>
</ButtonGroup>
<Modal
open={recordPop}
onClose={recordPopChange}
title={"Recording Data"}
title={"Press Spacebar or tap screen when you see RED circle"}
>
<Modal.Section>
<Card.Section>
@@ -223,11 +236,13 @@ export function renderRecord(recordPopChange, recordPop, status, Settings) {
}
function saveToCSV(Settings) {
const numSamplesToSave = 2000;
const numSamplesToSave = 10000;
console.log('Saving ' + numSamplesToSave + ' samples...');
var localObservable$ = null;
const dataToSave = [];
window.marker = 0;
window.responseMarker = 0;
window.touchMarker = 0;
console.log('making ' + Settings.name + ' headers')
@@ -242,6 +257,8 @@ function saveToCSV(Settings) {
dataToSave.push(
"Timestamp (ms),",
"Marker,",
"SpaceBar,",
"TouchMarker,",
generateXTics(x.info.samplingRate,x.data[0].length,false).map(function(f) {return "ch0_" + f + "ms"}) + ",",
generateXTics(x.info.samplingRate,x.data[0].length,false).map(function(f) {return "ch1_" + f + "ms"}) + ",",
generateXTics(x.info.samplingRate,x.data[0].length,false).map(function(f) {return "ch2_" + f + "ms"}) + ",",
@@ -260,7 +277,12 @@ function saveToCSV(Settings) {
// now with header in place subscribe to each epoch and log it
localObservable$.subscribe({
next(x) {
dataToSave.push(Date.now() + "," + window.marker + "," + Object.values(x).join(",") + "\n");
dataToSave.push(
Date.now() + "," +
window.marker + "," +
window.responseMarker + "," +
window.touchMarker + "," +
Object.values(x).join(",") + "\n");
// logging is useful for debugging -yup
// console.log(x);
},
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 224 KiB

@@ -1,30 +1,61 @@
export default function sketchEvoked (p) {
let x = 0;
let x = 0;
let thisRand = 0.5; //for random choice of target type
let targProp = 0.25;
let isTarget = false;
p.setup = function () {
p.createCanvas(300, 300);
p.frameRate(30);
p.noStroke();
};
p.windowResized = function() {
p.createCanvas(300, 300);
}
p.mousePressed = function () {
p.background(256);
p.touchStarted = function() {
if (window.touchMarker === 0) {
window.touchMarker = 255;
} else {
window.touchMarker = 0;
}
}
p.draw = function () {
if (p.keyIsPressed === true) {
window.responseMarker = p.keyCode;
} else {
window.responseMarker = 0;
}
p.background(255);
x = x+1;
if (x % 11 === 0) {
p.fill(0, 0, 0);
window.marker = 1;
} else {
// var num = int(random(0, 11));
if (x % 20 === 0) { // When a target shown (every ith frame for now)
thisRand = p.random();
if (thisRand < targProp) { // targets 20% of the time
isTarget = true;
} else {
isTarget = false;
}
if (isTarget) {
p.fill(250, 150, 150);
window.marker = 20;
} else {
p.fill(150,150,250);
window.marker = 10;
}
} else { // during time between targets
p.fill(255, 255, 255);
window.marker = 0;
}
p.noStroke();
p.ellipse(p.width/2, p.height/2, 300);
p.fill(255,0,0);
p.text("+", p.width/2, p.height/2);