Almost finished main static MT logic

This commit is contained in:
2018-12-02 19:52:37 +00:00
parent 10742cbec3
commit c57dc48cc4
8 changed files with 151 additions and 58 deletions
+47 -26
View File
@@ -6,12 +6,14 @@ from pysndfile import PySndfile, sndio
from random import randint, shuffle
from shutil import copyfile
from natsort import natsorted
import numpy as np
from matrix_test.signalops import play_wav
from scipy.special import logit
from config import socketio
import csv
import pdb
import dill
def roll_independant(A, r):
rows, column_indices = np.ogrid[:A.shape[0], :A.shape[1]]
@@ -62,6 +64,8 @@ class EEGTestThread(Thread):
self.question = []
self.socketio.on_event('eeg_page_loaded', self.setPageLoaded, namespace='/main')
self.socketio.on_event('submit_eeg_response', self.submitTestResponse, namespace='/main')
self.socketio.on_event('finish_eeg_test', self.finishTestEarly, namespace='/main')
# Percent speech inteligibility (estimated using behavioural measure)
# to present stimuli at
self.si = np.array([20.0, 35.0, 50.0, 65.0, 80.0, 90.0, 100.0])
@@ -70,6 +74,9 @@ class EEGTestThread(Thread):
self.clinPageLoaded = False
self.partPageLoaded = False
self.newResp = False
self.finishTest = True
self.trial_ind = 0
self._stopevent = Event()
# Attach messages from gui to class methods
@@ -100,16 +107,13 @@ class EEGTestThread(Thread):
self.waitForPageLoad()
self.socketio.emit('eeg_test_ready', namespace='/main')
# For each stimulus
for wav, q in zip(self.wav_files, self.question):
for ind, (wav, q) in enumerate(zip(self.wav_files, self.question)):
self.trial_ind = ind
if self._stopevent.isSet():
break
# Play concatenated matrix sentences at set SNR
self.playStimulus(wav)
self.setMatrix(q)
self.waitForResponse()
if self._stopevent.isSet():
return
self.saveState(out=self.backupFilepath)
self.saveState(out=self.backupFilepath)
if not self._stopevent.isSet():
self.unsetPageLoaded()
@@ -119,14 +123,35 @@ class EEGTestThread(Thread):
def setMatrix(self, questions):
'''
'''
for q in questions:
self.socketio.emit('set_matrix', {'data': q}, namespace='/main')
set_trace()
for self.q_ind, q in enumerate(questions):
self.answer = q[1]
question = q[0]
self.socketio.emit('set_matrix', {'data': question}, namespace='/main')
self.waitForResponse()
if self._stopevent.isSet():
return
self.processResponse()
self.saveState(out=self.backupFilepath)
def processResponse(self):
'''
'''
self.newResp = False
symb_dict = {
True: 10003,
False: 10007
}
try:
self.answers[self.trial_ind, self.q_ind] = self.answer in self.response
symb = symb_dict[self.answers[self.trial_ind, self.q_ind]]
except:
set_trace()
self.socketio.emit('eeg_test_resp', {'q_ind': self.q_ind, 'trial_ind': self.trial_ind, "ans": symb}, namespace='/main')
def finishTestEarly(self):
'''
'''
self._stopevent.set()
def join(self, timeout=None):
@@ -154,22 +179,18 @@ class EEGTestThread(Thread):
def finaliseResults(self):
toSave = ['snrTrack', 'trialN', 'wordsCorrect', 'presentedWords', 'responses']
toSave = ['marker_files', 'clinPageLoaded', 'wav_files', 'participant',
'response', 'pageLoaded', 'backupFilepath', 'noise_path',
'question_files', 'partPageLoaded', 'si', 'question', 'answers']
saveDict = {k:self.__dict__[k] for k in toSave}
if self.participant:
self.participant['adaptive_matrix_data'].update(saveDict)
self.participant.save("adaptive_matrix_data")
backup_path = os.path.join(self.participant.data_paths['adaptive_matrix_data'],
'finalised_backup.pkl')
copy2(self.backupFilepath, backup_path)
else:
copy2(self.backupFilepath, './finalised_backup.pkl')
with open('./Matrix_test_results.pkl', 'wb') as f:
dill.dump(saveDict, f)
self.participant['eeg_test_data'].update(saveDict)
self.participant.save("eeg_test_data")
backup_path = os.path.join(self.participant.data_paths['eeg_test_data'],
'finalised_backup.pkl')
copy2(self.backupFilepath, backup_path)
self.finalised = True
@staticmethod
def logisticFunction(L, L_50, s_50):
'''
@@ -253,6 +274,8 @@ class EEGTestThread(Thread):
c = list(zip(self.wav_files, self.marker_files))
shuffle(c)
self.wav_files, self.marker_files = zip(*c)
self.answers = np.empty(np.shape(self.question)[:2])
self.answers[:] = np.nan
def loadNoise(self, noiseFilepath):
@@ -285,12 +308,10 @@ class EEGTestThread(Thread):
self.newResp = True
def saveState(self, out="mat_state.pkl"):
toSave = ['listsRMS', 'y', 'currentList', 'slope', 'snr', 'snrTrack',
'direction', 'noise_rms', 'i', 'currentWords', 'usedLists',
'availableSentenceInds', 'trialN', 'listsString', 'noise',
'fs', 'nCorrect', 'loadedLists', 'lists', 'listN',
'wordsCorrect', 'responses', 'presentedWords']
def saveState(self, out="eeg_test_state.pkl"):
toSave = ['marker_files', 'clinPageLoaded', 'wav_files', 'participant',
'response', 'pageLoaded', 'backupFilepath', 'noise_path',
'question_files', 'partPageLoaded', 'si', 'question', 'answers']
saveDict = {k:self.__dict__[k] for k in toSave}
with open(out, 'wb') as f:
dill.dump(saveDict, f)
+14
View File
@@ -48,9 +48,23 @@
height: calc(90% - 56px);
}
.eeg_submit > button {
display: block;
text-decoration: none;
text-align: center;
align-items: stretch;
border-radius: 0px;
width: 100%;
height: 10%;
}
.center {
display: block;
margin-left: auto;
margin-right: auto;
height:100%;
}
#eeg_test_table td {
text-align: center;
}
+59 -6
View File
@@ -1,11 +1,47 @@
{% extends 'index.html' %}
{% block content %}
<div id="main-div">
<div class="card">
<div class="card-body">
<div id="progress-div" class="progress">
<div id="progress" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%"></div>
</div>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class="card">
<div id="main-div" class="card-body">
<table id="eeg_test_table" class="table table-sm table">
<thead class="thead-dark">
<tr>
<th scope="col">Trial #</th>
<th scope="col">1</th>
<th scope="col">2</th>
<th scope="col">3</th>
<th scope="col">4</th>
<th scope="col">5</th>
<th scope="col">6</th>
<th scope="col">7</th>
</tr>
</thead>
<tbody>
<tr id="Q1">
<th scope="row">Q1</th>
<td class="T1">-</td>
<td class="T2">-</td>
<td class="T3">-</td>
<td class="T4">-</td>
<td class="T5">-</td>
<td class="T6">-</td>
<td class="T7">-</td>
</tr>
<tr id="Q2">
<th scope="row">Q2</th>
<td class="T1">-</td>
<td class="T2">-</td>
<td class="T3">-</td>
<td class="T4">-</td>
<td class="T5">-</td>
<td class="T6">-</td>
<td class="T7">-</td>
</tr>
</tbody>
</table>
<div class="d-flex justify-content-center mt-2" role="group">
<button type="button" id="eeg_test_save" class="btn btn-primary mx-3">Save test state</button>
<button type="button" id="eeg_test_finish" class="btn btn-primary mx-3">Finish test</button>
</div>
</div>
</div>
@@ -16,6 +52,13 @@
// Check if matrix stimulus is currently being processed
waitingDialog.show('Generating stimulus');
socket.on('eeg_test_resp', function(msg) {
var t_ind = msg['trial_ind'];
var q_ind = msg['q_ind'];
$(`#Q${q_ind+1} > .T${t_ind+1}`).text(String.fromCharCode(msg['ans']));
});
socket.on('eeg_test_ready', function(msg) {
waitingDialog.hide();
});
@@ -23,6 +66,16 @@
socket.on('check-loaded', function(msg) {
socket.emit('eeg_page_loaded', {data: "clinician"});
});
$('#eeg_test_finish').click(function(event) {
socket.emit("finish_eeg_test")
});
// Catch message when asynchronous process is complete
socket.on('processing-complete', function(msg) {
alert("Matrix stimulus processing complete!")
window.location.href = '/eeg/test/clinician/complete';
});
});
</script>
{% endblock %}
+17 -8
View File
@@ -63,8 +63,8 @@
<button type="button" href="#" data-toggle="button" aria-pressed="false" disabled id="mat-3" class="Btn Btn-outline-secondary mat-button">big</button>
<button type="button" href="#" data-toggle="button" aria-pressed="false" disabled id="mat-4" class="Btn Btn-outline-secondary mat-button">beds</button>
</div>
<div class="mat_submit">
<button type="button" href="#" disabled id="mat-submit" class="Btn Btn-primary">Submit</button>
<div class="eeg_submit">
<button type="button" href="#" disabled id="eeg-submit" class="Btn Btn-primary">Submit</button>
</div>
<div id="overlay">
<span id="overlay_crosshair">&#10010;</span>
@@ -99,13 +99,13 @@
});
socket.on('eeg_stim_done', function(msg) {
$('.eeg_submit').find('input, textarea, button, select').removeAttr('disabled');
off()
});
socket.on('set_matrix', function(msg) {
var q = msg['data'][0];
var q = msg['data'];
q = q.split(" ")
var ans = msg['data'][1];
for(i = 0; i < q.length; i++) {
entry = q[i]
var buttons = $(`.mat-button#mat-${i}`)
@@ -119,8 +119,10 @@
buttons.not(`:contains(${entry})`).attr('disabled','disabled');
$(`.mat-button:contains(${entry})`).addClass("active");
$(`.mat-button:contains(${entry})`).attr("aria-pressed", "true");
choice[i] = entry.toUpperCase();
}
}
$('#eeg-submit').prop("disabled", false);
});
function on() {
@@ -134,21 +136,28 @@
$("#overlay").fadeOut();
}
$('#mat-submit').click(function(event) {
$('#mat-submit').prop("disabled", true);
$('#eeg-submit').click(function(event) {
$('#eeg-submit').prop("disabled", true);
if(choice.includes('')) {
alert("Please select a word from each column");
$('#mat-submit').prop("disabled", false);
$('#eeg-submit').prop("disabled", false);
return false;
}
else {
$('.mat-button').removeClass("active");
socket.emit('submit_mat_response', {
socket.emit('submit_eeg_response', {
resp: choice
});
choice = Array(5).fill('');
}
});
socket.on('processing-complete', function(msg) {
// Re-enable all inputs
$('#main-div').find('input, textarea, button, select').removeAttr('disabled');
alert("Matrix stimulus processing complete!")
window.location.href = '/eeg/test/complete';
});
});
</script>
{% endblock %}
-8
View File
@@ -105,14 +105,6 @@
$('#progress').css("width", msg.data);
});
// Catch message when asynchronous process is complete
socket.on('processing-complete', function(msg) {
// Re-enable all inputs
$('#main-div').find('input, textarea, button, select').removeAttr('disabled');
alert("Matrix stimulus processing complete!")
window.location.href = '/matrix_test/clinician/complete';
});
socket.on('main-notification', function(msg) {
alert(msg.data)
});
+9
View File
@@ -41,6 +41,15 @@ $(document).ready(function(){
socket.on('check-loaded', function(msg) {
socket.emit('mat_page_loaded', {data: "clinician"});
});
// Catch message when asynchronous process is complete
socket.on('processing-complete', function(msg) {
// Re-enable all inputs
$('#main-div').find('input, textarea, button, select').removeAttr('disabled');
alert("Matrix stimulus processing complete!")
window.location.href = '/matrix_test/clinician/complete';
});
});
</script>
{% endblock %}
+5 -1
View File
@@ -105,8 +105,12 @@
$('#main-div').find('input, textarea, button, select').removeAttr('disabled');
});
// Catch message when asynchronous process is complete
socket.on('processing-complete', function(msg) {
$('#main-div').find('input, textarea, button, select').attr('disabled','disabled');
// Re-enable all inputs
$('#main-div').find('input, textarea, button, select').removeAttr('disabled');
alert("Matrix stimulus processing complete!")
window.location.href = '/matrix_test/complete';
});
socket.on('check-loaded', function(msg) {
-9
View File
@@ -67,15 +67,6 @@
socket.on('participant_start_mat', function() {
window.location.href = "/matrix_test/run";
});
// Catch message when asynchronous process is complete
socket.on('processing-complete', function(msg) {
// Re-enable all inputs
$('#main-div').find('input, textarea, button, select').removeAttr('disabled');
alert("Matrix stimulus processing complete!")
window.location.href = '/matrix_test/complete';
});
});
</script>
</body>