Checked over click playing logic

This commit is contained in:
2019-01-25 16:36:36 +00:00
parent bb9994436a
commit de5a141d63
16 changed files with 88 additions and 69 deletions
+4 -19
View File
@@ -65,43 +65,28 @@ class ClickTestThread(BaseThread):
'''
self.waitForPageLoad()
self.socketio.emit('test_ready', namespace='/main')
for self.trial_ind in range(self.nTrials):
for self.trial_ind in range(self.trial_ind, self.nTrials):
self.displayInstructions()
self.waitForPartReady()
if self._stopevent.isSet() or self.finishTest:
break
# Play concatenated matrix sentences at set SNR
self.playStimulus(self.wav_file)
self.playStimulusWav(self.wav_file)
self.saveState(out=self.backupFilepath)
if not self._stopevent.isSet():
self.unsetPageLoaded()
self.socketio.emit('processing-complete', namespace='/main')
self.waitForFinalise()
def displayInstructions(self):
self.socketio.emit('display_instructions', namespace='/main')
def playStimulus(self, wav_file, replay=False):
self.newResp = False
self.socketio.emit("stim_playing", namespace="/main")
# if not replay:
# self.y = self.generateTrial(self.snr)
# Play audio
# sd.play(self.y, self.fs, blocking=True)
if not self.dev_mode:
self.play_wav(wav_file, 'finish_test')
else:
self.play_wav('./test.wav', 'finish_test')
self.socketio.emit("stim_done", namespace="/main")
def loadStimulus(self):
'''
'''
#audio, fs, enc, fmt = sndio.read(wav, return_format=True)
pass
def saveState(self, out="test_state.pkl"):
saveDict = {k:self.__dict__[k] for k in self.toSave}
+6 -6
View File
@@ -14,12 +14,12 @@ server_lock = Lock()
logger = logging.getLogger(__name__)
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
log = logging.getLogger('engineio')
log.setLevel(logging.ERROR)
log = logging.getLogger('socketio')
log.setLevel(logging.ERROR)
# log = logging.getLogger('werkzeug')
# log.setLevel(logging.ERROR)
# log = logging.getLogger('engineio')
# log.setLevel(logging.ERROR)
# log = logging.getLogger('socketio')
# log.setLevel(logging.ERROR)
def url_ok(url, port):
+30 -28
View File
@@ -92,7 +92,7 @@ class MatTestThread(BaseThread):
self.srt_50 = None
self.s_50 = None
self.wordsCorrect = np.full((90, 5), False, dtype=bool)
self.wordsCorrect = np.full((180, 5), False, dtype=bool)
self.trialN = 0
self.availableSentenceInds = []
@@ -111,13 +111,14 @@ class MatTestThread(BaseThread):
'wordsCorrect', 'trialN', 'test_name', 'backupFilepath',
'currentWords', 'nCorrect', 'availableSentenceInds',
'lists', 'listsRMS', 'listsString']
self.toFinalise = ['snrTrack', 'trackOrder', 'trialN', 'wordsCorrect',
self.toFinalise = ['trackSNR', 'trackOrder', 'trialN', 'wordsCorrect',
'presentedWords', 'responses', 'srt_50', 's_50']
# Attach messages from gui to class methods
self.socketio.on_event('submit_response', self.submitMatResponse, namespace='/main')
self.socketio.on_event('page_loaded', self.setPageLoaded, namespace='/main')
self.socketio.on_event('repeat_stimulus', self.playStimulusSocketHandle, namespace='/main')
self.socketio.on_event('finalise_results', self.finaliseResults, namespace='/main')
self.loadNoise(noiseFilepath, noiseRMSFilepath)
@@ -132,7 +133,7 @@ class MatTestThread(BaseThread):
dpi = 300
maxTrialN = np.max([x.trialN for x in self.adaptiveTracks])
plt.xlim([-1, maxTrialN])
plt.xlim([-1, maxTrialN+1])
plt.savefig(self.img, format='png', figsize=(800/dpi, 800/dpi), dpi=dpi)
self.img.seek(0)
plot_url = base64.b64encode(self.img.getvalue()).decode()
@@ -148,7 +149,7 @@ class MatTestThread(BaseThread):
self.displayInstructions()
self.waitForPartReady()
while not self.finishTest and not self._stopevent.isSet() and len(self.availableSentenceInds):
while not self.finishTest and not self._stopevent.isSet() and len(self.availableSentenceInds) and len(self.trackOrder):
# Plot SNR of current trial to the clinician screen
for at in self.adaptiveTracks:
at.plotSNR()
@@ -176,6 +177,7 @@ class MatTestThread(BaseThread):
self.checkSentencesAvailable()
self.saveState(out=self.backupFilepath)
self.trialN += 1
self.adaptiveTracks[self.adTrInd].incrementTrialN()
self.saveState(out=self.backupFilepath)
if not self._stopevent.isSet():
self.unsetPageLoaded()
@@ -189,21 +191,6 @@ class MatTestThread(BaseThread):
self.waitForFinalise()
def finaliseResults(self):
saveDict = {k:self.__dict__[k] for k in self.toFinalise}
if self.participant:
self.participant[self.test_name].update(saveDict)
self.participant.save(self.test_name)
backup_path = os.path.join(self.participant.data_paths[self.test_name],
'finalised_backup.pkl')
copy2(self.backupFilepath, backup_path)
else:
copy2(self.backupFilepath, './finalised_backup.pkl')
with open('./{}_results.pkl'.format(self.test_name), 'wb') as f:
dill.dump(saveDict, f)
self.finalised = True
@staticmethod
def logisticFunction(L, L_50, s_50):
@@ -246,9 +233,8 @@ class MatTestThread(BaseThread):
def fitLogistic(self):
'''
'''
self.wordsCorrect = [x.getWordsCorrect() for x in self.adaptiveTracks]
self.trackSNR = [x.getSNRTrack() for x in self.adaptiveTracks]
set_trace()
self.wordsCorrect = np.concatenate([x.getWordsCorrect() for x in self.adaptiveTracks])
self.trackSNR = np.concatenate([x.getSNRTrack() for x in self.adaptiveTracks])
res = minimize(self.logisticFuncLiklihood, np.array([np.mean(self.trackSNR),1.0]))
percent_correct = (np.sum(self.wordsCorrect, axis=1)/self.wordsCorrect.shape[1])*100.
sortedSNRind = np.argsort(-self.trackSNR)
@@ -412,6 +398,21 @@ class MatTestThread(BaseThread):
with open(out, 'wb') as f:
dill.dump(saveDict, f)
def finaliseResults(self):
saveDict = {k:self.__dict__[k] for k in self.toFinalise}
saveDict['adaptiveTracks'] = []
for ind, _ in enumerate(self.adaptiveTracks):
atDict = self.adaptiveTracks[ind].createSaveDict()
saveDict['adaptiveTracks'].append(atDict)
self.participant[self.test_name].update(saveDict)
self.participant.save(self.test_name)
backup_path = os.path.join(self.participant.data_paths[self.test_name],
'finalised_backup.pkl')
copy2(self.backupFilepath, backup_path)
set_trace()
self.finalised = True
class AdaptiveTrack():
'''
'''
@@ -421,13 +422,13 @@ class AdaptiveTrack():
self.snr = 0.0
self.direction = 0
# Record SNRs presented with each trial of the adaptive track
self.snrTrack = np.empty(90)
self.snrTrack = np.empty(180)
self.snrTrack[:] = np.nan
self.snrTrack[0] = 0.0
# Count number of presented trials
self.trialN = 0
self.reduction_coef = np.load(red_coef)*np.load(cal_coef)
self.wordsCorrect = np.full((90, 5), False, dtype=bool)
self.wordsCorrect = np.full((180, 5), False, dtype=bool)
# Adaptive track parameters
self.slope = 0.15
@@ -454,6 +455,9 @@ class AdaptiveTrack():
def processResponse(resp):
pass
def incrementTrialN(self):
self.trialN += 1
def generateTrial(self, x, x_rms):
# Convert desired SNR to dB FS
@@ -489,16 +493,14 @@ class AdaptiveTrack():
self.i += 1
self.direction = currentDirection
self.snrTrack[self.trialN] = self.snr
self.trialN += 1
print("Track {0} trial N: {1}".format(self.target, self.trialN))
def plotSNR(self):
'''
'''
plt.plot(self.snrTrack, 'o-')
plt.ylim([20.0, -20.0])
plt.xticks(np.arange(90))
plt.ylim([20.0, -30.0])
plt.xticks(np.arange(180))
plt.xlabel("Trial N")
plt.ylabel("SNR (dB)")
plt.title("Adaptive track")
+11
View File
@@ -262,3 +262,14 @@ Calibration routing
@server.route('/calibrate')
def calibrate():
return render_template("calibrate.html")
'''
Basic audiology test routing
'''
@server.route('/pta_test')
def pta():
return render_template("pta.html")
@server.route('/tympanometry')
def typms():
return render_template("tympanometry.html")
+2
View File
@@ -15,6 +15,8 @@ $(document).ready(function(){
$('#mat-save').click(function(event) {
socket.emit("finalise_results")
});
socket.on('test_finished', function(msg) {
window.location.href = '/home';
});
});
+2 -2
View File
@@ -62,11 +62,11 @@
waitingDialog.hide();
});
socket.on('stim_playing', function(msg) {
socket.on('click_test_stim_playing', function(msg) {
on()
});
socket.on('stim_done', function(msg) {
socket.on('click_test_stim_done', function(msg) {
off()
});
+2
View File
@@ -15,6 +15,8 @@ $(document).ready(function(){
$('#mat-save').click(function(event) {
socket.emit("finalise_results")
});
socket.on('test_finished', function(msg) {
window.location.href = '/home';
});
});
@@ -42,6 +42,8 @@ $(document).ready(function(){
$('#mat-save').click(function(event) {
socket.emit("finalise_results")
});
socket.on('test_finished', function(msg) {
window.location.href = '/home';
});
+9 -1
View File
@@ -64,15 +64,23 @@
</tbody>
</table>
</div>
<div class="d-flex justify-content-center mt-2" role="group">
<button type="button" id="mat-save" class="btn btn-primary mx-3">Save and finish test</button>
</div>
</div>
<script>
$(document).ready(function(){
// Initialise socketio with a namespace called "main"
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + '/main');
socket.on('test_resp', function(msg) {
console.log("Yup");
$(`#Q1 > .T${parseInt(msg['trial_ind'])+1} > button`).attr("data-original-title", msg['ans']).tooltip('show');
});
$('#mat-save').click(function(event) {
socket.emit("finalise_results")
});
socket.on('test_finished', function(msg) {
window.location.href = '/home';
});
});
</script>
{% endblock %}
+2
View File
@@ -114,6 +114,8 @@ $(document).ready(function(){
$('#mat-save').click(function(event) {
socket.emit("finalise_results")
});
socket.on('test_finished', function(msg) {
window.location.href = '/home';
});
-1
View File
@@ -42,7 +42,6 @@
margin-right: auto;
height:100%;
}
</style>
</head>
+2
View File
@@ -32,6 +32,8 @@ $(document).ready(function(){
$('#mat-save').click(function(event) {
socket.emit("finalise_results")
finalised=1;
});
socket.on('test_finished', function(msg) {
window.location.href = '/home';
});
+5 -4
View File
@@ -6,10 +6,11 @@
<div class="card-body">
<h2>Instructions</h2>
<p>
In this test, you will be presented with repeated "da"
utterances. Simply listen to the stimulus, you do not need to
respond.
</p>
In this test, you will be presented with sentences spoken in
background noise. Use the grid to select the word you hear from
each column. If you can't hear a word, take a guess. When you
have made your selection, press submit to continue to the next
sentence.</p>
<button type="button" href="#" id="instr_continue" class="Btn Btn-primary">Continue</button>
</div>
</div>
+1 -1
View File
@@ -20,7 +20,7 @@
<div class="form-group">
<label for="listN">Number of lists:</label>
<br>
<input id="listN" name="listN" type="number" value="3" max="18" min="1" style="width:85%">
<input id="listN" name="listN" type="number" value="5" max="18" min="1" style="width:85%">
</div>
<div class="form-group d-flex justify-content-center">
<button type="button" id="submit" class="btn btn-primary mx-3">Start new test</button>
+1
View File
@@ -1,5 +1,6 @@
<html>
<link rel="stylesheet" media="screen" href = "{{ url_for('static', filename='bootstrap.min.css') }}">
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<meta name="viewport" content = "width=device-width, initial-scale=1.0">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
+9 -7
View File
@@ -78,7 +78,7 @@ class BaseThread(Thread):
self.dev_mode = False
def play_wav(self, wav_file, stop_string):
def play_wav(self, wav_file, stop_string='stop_audio'):
self.wavThread = WavPlayer(wav_file, socketio=socketio, stop_string=stop_string)
self.wavThread.run()
@@ -153,8 +153,11 @@ class BaseThread(Thread):
Wait for results to be finalised by socketio handler
'''
while not self.finalised and not self._stopevent.isSet() and not self.finishTest:
print(self.finishTest)
print("self.finalised {}".format(self.finalised))
print("self.finishTest {}".format(self.finishTest))
print("self._stopevent {}".format(self._stopevent))
self._stopevent.wait(0.2)
self.socketio.emit("test_finished", namespace='/main')
return
@@ -175,11 +178,11 @@ class BaseThread(Thread):
self.newResp = False
self.socketio.emit("{}_stim_playing".format(self.test_name), namespace="/main")
if not self.dev_mode:
play_wav(wav_file)
self.play_wav(wav_file)
else:
play_wav('./da_stim/DA_170.wav')
self.play_wav('./da_stim/DA_170.wav')
self.socketio.emit("{}_stim_done".format(test_name), namespace="/main")
self.socketio.emit("{}_stim_done".format(self.test_name), namespace="/main")
def playStimulus(self, y, fs):
@@ -231,8 +234,6 @@ class BaseThread(Thread):
self.clinPageLoaded = True
else:
self.partPageLoaded = True
print("PART: {}".format(self.partPageLoaded))
print("CLIN: {}".format(self.clinPageLoaded))
self.pageLoaded = self.clinPageLoaded and self.partPageLoaded
@@ -261,6 +262,7 @@ class BaseThread(Thread):
previously generated pickle file
'''
filepath = msg['data']
set_trace()
self.loadState(filepath)