Fixed backup bug in MT and continued implementing per participant testing

This commit is contained in:
2018-11-24 19:30:20 +00:00
parent 03c3e20855
commit f6e390914e
4 changed files with 80 additions and 40 deletions
+35 -13
View File
@@ -4,8 +4,23 @@ from threading import Thread, Event
import io
import dill
import base64
import os
import random
from scipy.optimize import minimize
import csv
from pysndfile import sndio
from matrix_test.filesystem import globDir
import sounddevice as sd
import pdb
def set_trace():
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
log = logging.getLogger('engineio')
log.setLevel(logging.ERROR)
pdb.set_trace()
def find_nearest_idx(array, value):
'''
Adapted from: https://stackoverflow.com/questions/2566412/find-nearest-value-in-numpy-array
@@ -28,8 +43,9 @@ class MatTestThread(Thread):
Thread for running server side matrix test operations
'''
def __init__(self, listN=3, sessionFilepath=None, noiseFilepath="./matrix_test/stimulus/wav/noise/noise.wav",
listFolder="./matrix_test/stimulus/wav/sentence-lists/", socketio=None):
listFolder="./matrix_test/stimulus/wav/sentence-lists/", socketio=None, participant=None):
super(MatTestThread, self).__init__()
self.participant=participant
self.newResp = False
self.foundSRT = False
self.pageLoaded = False
@@ -80,6 +96,12 @@ class MatTestThread(Thread):
self._stopevent = Event()
if self.participant:
folder = self.participant.data_paths['adaptive_matrix_data']
self.backupFilepath=os.path.join(folder, 'mat_state.pik')
else:
self.backupFilepath='./mat_state.pik'
# If loading session from file, load session variables from the file
if sessionFilepath:
self.loadState(sessionFilepath)
@@ -103,16 +125,14 @@ class MatTestThread(Thread):
if self._stopevent.isSet():
return
self.calcSNR()
self.saveState()
self.saveState(out=self.backupFilepath)
self.saveState(out=self.backupFilepath)
if not self._stopevent.isSet():
self.unsetPageLoaded()
self.socketio.emit('processing-complete', {'data': ''}, namespace='/main')
self.waitForPageLoad()
self.plotSNR()
self.fitLogistic()
self.saveState()
#socketio.emit('update-progress', {'data': '{}%'.format(percent)}, namespace='/main')
def finishTestEarly(self):
@@ -297,12 +317,12 @@ class MatTestThread(Thread):
def playStimulus(self, replay=False):
self.newResp = False
socketio.emit("mat_stim_playing", namespace="/main")
self.socketio.emit("mat_stim_playing", namespace="/main")
if not replay:
self.y = self.generateTrial(self.snr)
# Play audio
sd.play(self.y, self.fs, blocking=True)
socketio.emit("mat_stim_done", namespace="/main")
self.socketio.emit("mat_stim_done", namespace="/main")
def loadStimulus(self, listDir, n=3, demo=False):
@@ -399,14 +419,16 @@ class MatTestThread(Thread):
def saveState(self, out="mat_state.pik"):
toSave = ['listsRMS', 'y', 'currentList', 'foundSRT', 'slope', 'snr',
'snrTrack', 'direction', 'noise_rms', 'i', 'currentWords',
'usedLists', 'availableSentenceInds', 'trialN',
'listsString', 'noise', 'fs', 'nCorrect', 'loadedLists',
'lists', 'listN', 'wordsCorrect']
toSave = ['listsRMS', 'y', 'currentList', 'slope', 'snr', 'snrTrack',
'direction', 'noise_rms', 'i', 'currentWords', 'usedLists',
'availableSentenceInds', 'trialN', 'listsString', 'noise',
'fs', 'nCorrect', 'loadedLists', 'lists', 'listN',
'wordsCorrect']
saveDict = {k:self.__dict__[k] for k in toSave}
with open(out, 'wb') as f:
dill.dump(saveDict, f)
if self.participant:
self.participant['adaptive_matrix_data'].update(saveDict)
def manualSave(self, msg):
@@ -431,4 +453,4 @@ class MatTestThread(Thread):
'''
This function is called when the thread starts
'''
self.testLoop()
return self.testLoop()
+33 -11
View File
@@ -16,7 +16,6 @@ import re
import base64
import shutil
import sounddevice as sd
import webview
import webbrowser
import app
@@ -69,12 +68,14 @@ class StimGenThread(Thread):
socketio.emit('processing-complete', {'data': ''}, namespace='/main')
def run_matrix_thread(listN=None, sessionFilepath=None):
def run_matrix_thread(listN=None, sessionFilepath=None, participant=None):
global matThread
if 'matThread' in globals():
if matThread.isAlive() and isinstance(matThread, MatTestThread):
matThread.join()
matThread = MatTestThread(socketio=socketio, listN=listN, sessionFilepath=sessionFilepath)
matThread = MatTestThread(socketio=socketio, listN=listN,
sessionFilepath=sessionFilepath,
participant=participant)
matThread.start()
@@ -120,7 +121,6 @@ def fullscreen():
def manage_participant_page():
# Find all pre-existing participants
participants = find_participants()
part_num = gen_participant_num(participants)
return render_template("manage_participants.html", part_keys=participants.keys())
@socketio.on('delete_participant', namespace='/main')
@@ -129,7 +129,7 @@ def manage_participant_delete(participant_str):
del participants[participant_str]
return render_template("manage_participants.html", part_keys=participants.keys())
@socketio.on('update_participant', namespace='/main')
@socketio.on('update_participant_info', namespace='/main')
def manage_participant_save(data):
key = "participant_{}".format(data['number'])
participants[key].set_info(data)
@@ -221,7 +221,8 @@ def homepage():
@server.route('/matrix_test')
def matrix_test_setup():
return render_template("matrix_test_setup.html")
participants = find_participants()
return render_template("matrix_test_setup.html", part_keys=participants.keys())
@server.route('/matrix_test/run')
def run_matrix_test():
@@ -242,6 +243,7 @@ def clinician_mat_end():
@server.route('/matrix_test/stimulus_generation')
def matDecStim():
return render_template("matrix_decode_stim.html")
@socketio.on('start_mat_test', namespace='/main')
def start_mat_test(msg):
'''
@@ -249,22 +251,36 @@ def start_mat_test(msg):
'''
socketio.emit('participant_start_mat', {'data': ''}, namespace='/main', broadcast=True)
listN = int(msg['listN'])
part_key = msg['part_key']
run_matrix_thread(listN=listN)
if part_key != "--":
participant = participants[part_key]
else:
participant = None
run_matrix_thread(listN=listN, participant=participant)
@socketio.on('load_mat_backup', namespace='/main')
def start_backup_mat_test():
def start_backup_mat_test(msg):
'''
Relay test start message to participant view
'''
socketio.emit('participant_start_mat', {'data': ''}, namespace='/main', broadcast=True)
part_key = msg['part_key']
if part_key != "--":
participant = participants[part_key]
folder = participant.data_paths["adaptive_matrix_data"]
backupPath = os.path.join(folder, "mat_state.pik")
else:
participant = None
backupPath = './mat_state.pik'
run_matrix_thread(sessionFilepath="./mat_state.pik")
run_matrix_thread(sessionFilepath=backupPath)
@socketio.on('load_mat_session', namespace='/main')
def start_saved_mat_test():
def start_saved_mat_test(msg):
'''
Relay test start message to participant view
'''
@@ -275,8 +291,14 @@ def start_saved_mat_test():
filepath = filepath.decode("utf-8")
else:
return None
part_key = msg['part_key']
if part_key != "--":
participant = participants[part_key]
else:
participant = None
socketio.emit('participant_start_mat', {'data': ''}, namespace='/main', broadcast=True)
run_matrix_thread(sessionFilepath=filepath)
run_matrix_thread(sessionFilepath=filepath, participant=participant)
@socketio.on('run_mat_stim_gen', namespace='/main')
+1 -1
View File
@@ -81,7 +81,7 @@ $(document).ready(function(){
handedness: $('#handedness').val(),
general_notes: $('#general_notes').val()
}
socket.emit('update_participant', form_data);
socket.emit('update_participant_info', form_data);
});
$('#delete').click(function(event) {
+11 -15
View File
@@ -3,18 +3,20 @@
<div class="card">
<div id="main-div" class="card-body">
<form action="{{ url_for('matDecStim') }}" method="POST">
<div class="form-group">
<select class="form-control" name="participant" id="participant">
<option>--</option>
{% for p in part_keys %}
<option>{{ p }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="open-mat-folder-container">Matrix data folder: </label>
<br>
<input type="text" id="mat-dir" name='mat_dir' value="./matrix_test/speech_components/" style="width:85%"></input>
<button type="button" id="mat-dir-button" class="btn btn-primary">Browse...</button>
</div>
<div class="form-group">
<label for="open-save-folder-container">New data generation folder: </label>
<br>
<input type="text" id="save-dir" name='save_dir' style="width:85%"></input>
<button type="button" id="save-dir-button" class="btn btn-primary">Browse...</button>
</div>
<div class="form-group">
<label for="listN">Number of lists:</label>
<br>
@@ -35,23 +37,17 @@
$('#load-backup').click(function(event) {
// Send message to call stimulus generation function in Python
socket.emit('load_mat_backup');
socket.emit('load_mat_backup', {part_key: $("#participant").val()});
return false;
})
$('#load-saved').click(function(event) {
// Send message to call stimulus generation function in Python
socket.emit('load_mat_session');
socket.emit('load_mat_session', {part_key: $("#participant").val()});
return false;
})
$('#submit').click(function(event) {
// Send message to call stimulus generation function in Python
socket.emit('start_mat_test', {listN: $("#listN").val()});
return false;
})
$('#save-dir-button').click(function(event) {
// Send message to call stimulus generation function in Python
socket.emit('open_save_dialog');
socket.emit('start_mat_test', {listN: $("#listN").val(), part_key: $("#participant").val()});
return false;
})