Added stim_part to word csv converter script

This commit is contained in:
2019-01-07 09:53:55 +00:00
parent 6af6f0b0c4
commit 996fd01062
14 changed files with 246 additions and 48 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
import pathops
import os
from matrix_test.generate_matrix_stimulus import generateAudioStimulus
from matrix_test.long_concat_stim.gen_long_stim import generateAudioStimulus
import time
import config
+2 -2
View File
@@ -1,7 +1,7 @@
from threading import Thread, Event
import os
import numpy as np
from matrix_test.filesystem import globDir
from matrix_test.helper_modules.filesystem import globDir
from pysndfile import PySndfile, sndio
from random import randint, shuffle
from shutil import copyfile
@@ -12,7 +12,7 @@ from shutil import copy2
from test_base import BaseThread
from matrix_test.signalops import play_wav
from matrix_test.helper_modules.signalops import play_wav
from scipy.special import logit
from config import socketio
import csv
+2 -2
View File
@@ -1,7 +1,7 @@
from threading import Thread, Event
import os
import numpy as np
from matrix_test.filesystem import globDir
from matrix_test.helper_modules.filesystem import globDir
from pysndfile import PySndfile, sndio
from random import randint, shuffle
from shutil import copyfile
@@ -12,7 +12,7 @@ from shutil import copy2
from test_base import BaseThread
from matrix_test.signalops import play_wav
from matrix_test.helper_modules.signalops import play_wav
from scipy.special import logit
from config import socketio
import csv
+197 -22
View File
@@ -1,7 +1,7 @@
from threading import Thread, Event
import os
import numpy as np
from matrix_test.filesystem import globDir
from matrix_test.helper_modules.filesystem import globDir
from pysndfile import PySndfile, sndio
from random import randint, shuffle
from shutil import copyfile
@@ -10,9 +10,7 @@ import numpy as np
import pandas as pd
from shutil import copy2
from test_base import BaseThread
from matrix_test.signalops import play_wav
from test_base import BaseThread, run_test_thread
from scipy.special import logit
from config import socketio
import csv
@@ -24,6 +22,17 @@ symb_dict = {
False: 10007
}
def roll_independant(A, r):
rows, column_indices = np.ogrid[:A.shape[0], :A.shape[1]]
# Use always a negative shift, so that column_indices are valid.
# (could also use module operation)
r[r < 0] += A.shape[1]
column_indices = column_indices - r[:,np.newaxis]
result = A[rows, column_indices]
return result
def set_trace():
import logging
log = logging.getLogger('werkzeug')
@@ -38,25 +47,128 @@ class EEGMatTrainThread(BaseThread):
Thread for running server side matrix test operations
'''
def __init__(self, sessionFilepath=None,
stimFolder='./da_stim/', nTrials=2,
listFolder="./matrix_test/short_concat_stim/out",
noiseFilepath="./matrix_test/behavioural_stim/stimulus/wav/noise/noise.wav",
socketio=None, participant=None, srt_50=None, s_50=None):
self.wav_file = os.path.join(stimFolder, '3000_da.wav')
self.noise_path = noiseFilepath
self.listDir = listFolder
self.test_name = 'da_test'
self.nTrials = nTrials
self.wav_files = []
self.marker_files = []
self.question_files = []
self.question = []
self.response = []
# 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])
self.trial_ind = 0
self._stopevent = Event()
super(DaTestThread, self).__init__(self.test_name,
super(EEGMatTrainThread, self).__init__('eeg_mat_train',
sessionFilepath=sessionFilepath,
socketio=socketio,
participant=participant)
self.toSave = ['trial_ind', 'nTrials', 'wav_file', 'test_name']
self.socketio.on_event('submit_eeg_response', self.submitTestResponse, namespace='/main')
self.socketio.on_event('finalise_results', self.finaliseResults, namespace='/main')
self.dev_mode = True
def loadStimulus(self):
'''
'''
self.participant.load('mat_test')
try:
srt_50=self.participant.data['mat_test']['srt_50']
s_50=self.participant.data['mat_test']['s_50']
except KeyError:
raise KeyError("Behavioural matrix test results not available, make "
"sure the behavioural test has been run before "
"running this test.")
# Estimate speech intelligibility thresholds using predicted
# psychometric function
reduction_coef = float(np.load(os.path.join(self.listDir, 'reduction_coef.npy')))
s_50 *= 0.01
x = logit(self.si * 0.01)
snrs = (x/(4*s_50))+srt_50
snr_map = pd.DataFrame({"speech_intel" : self.si, "snr": snrs})
save_dir = self.participant.data_paths['eeg_test/stimulus']
snr_map_path = os.path.join(save_dir, "snr_map.csv")
snr_map.to_csv(snr_map_path)
snrs = np.repeat(snrs[np.newaxis], 4, axis=0)
snrs = roll_independant(snrs, np.array([0,-1,-2,-3]))
noise_file = PySndfile(self.noise_path, 'r')
stim_dirs = [x for x in os.listdir(self.listDir) if os.path.isdir(os.path.join(self.listDir, x))]
shuffle(stim_dirs)
wav_files = []
question = []
marker_files = []
self.socketio.emit('test_stim_load', namespace='/main')
for ind, dir_name in enumerate(stim_dirs):
stim_dir = os.path.join(self.listDir, dir_name)
wav = globDir(stim_dir, "*.wav")[0]
csv_files = natsorted(globDir(stim_dir, "*.csv"))
marker_file = csv_files[0]
question_files = csv_files[1:]
rms_file = globDir(stim_dir, "*.npy")[0]
speech_rms = float(np.load(rms_file))
snr = snrs[:, ind]
audio, fs, enc, fmt = sndio.read(wav, return_format=True)
speech = audio[:, :2]
#triggers = audio[:, 2]
wf = []
for ind2, s in enumerate(snr):
start = randint(0, noise_file.frames()-speech.shape[0])
noise_file.seek(start)
noise = noise_file.read_frames(speech.shape[0])
noise_rms = np.sqrt(np.mean(noise**2))
snr_fs = 10**(-s/20)
if snr_fs == np.inf:
snr_fs = 0.
elif snr_fs == -np.inf:
raise ValueError("Noise infinitely louder than signal at snr: {}".format(snr))
noise = noise*(speech_rms/noise_rms)
out_wav_path = os.path.join(save_dir, "Stim_{0}_{1}.wav".format(ind, ind2))
out_meta_path = os.path.join(save_dir, "Stim_{0}_{1}.npy".format(ind, ind2))
with np.errstate(divide='raise'):
try:
out_wav = (speech+(np.stack([noise, noise], axis=1)*snr_fs))*reduction_coef
except:
set_trace()
#out_wav = np.concatenate([out_wav, triggers[:, np.newaxis]], axis=1)
sndio.write(out_wav_path, out_wav, fs, fmt, enc)
np.save(out_meta_path, snr)
wf.append(out_wav_path)
wav_files.append(wf)
out_marker_path = os.path.join(save_dir, "Marker_{0}.csv".format(ind))
marker_files.append(out_marker_path)
copyfile(marker_file, out_marker_path)
for q_file in question_files:
out_q_path = os.path.join(save_dir, "Questions_{0}_{1}.csv".format(ind, ind2))
self.question_files.append(out_q_path)
copyfile(q_file, out_q_path)
for q_file_path in question_files:
q = []
with open(q_file_path, 'r') as q_file:
q_reader = csv.reader(q_file)
for line in q_reader:
q.append(line)
question.append(q)
self.wav_files = [item for sublist in wav_files for item in sublist]
self.question.extend(question)
for item in marker_files:
self.marker_files.extend([item] * 4)
c = list(zip(self.wav_files, self.marker_files, self.question))
shuffle(c)
self.wav_files, self.marker_files, self.question = zip(*c)
self.answers = np.empty(np.shape(self.question)[:2])
self.answers[:] = np.nan
def testLoop(self):
@@ -64,22 +176,81 @@ class EEGMatTrainThread(BaseThread):
Main loop for iteratively finding the SRT
'''
self.waitForPageLoad()
self.socketio.emit('test_ready', namespace='/main')
for self.trial_ind in range(self.nTrials):
self.loadResponse()
self.socketio.emit(
'test_ready',
{'sentence_1': self.question[0][0][0], 'sentence_2':
self.question[0][1][0]}, namespace='/main'
)
# For each stimulus
trials = list(zip(self.wav_files, self.question))[self.trial_ind:]
for (wav, q) in trials:
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.playStimulus(wav)
self.setMatrix(q)
self.saveState(out=self.backupFilepath)
if not self._stopevent.isSet():
self.unsetPageLoaded()
self.socketio.emit('processing-complete', namespace='/main')
self.waitForPageLoad()
self.fillTable()
def displayInstructions(self):
self.socketio.emit('display_instructions', namespace='/main')
self.socketio.emit(
'display_instructions',
{'sentence_1': self.question[self.trial_ind][0][0], 'sentence_2':
self.question[self.trial_ind][1][0]}, namespace='/main'
)
def fillTable(self):
'''
'''
symb = [[symb_dict[x], symb_dict[y]] for x, y in self.answers if not np.isnan([x, y]).any()]
self.socketio.emit('test_fill_table', {'data': symb}, namespace='/main')
def setMatrix(self, questions):
'''
'''
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() or self.finishTest:
return
self.processResponse()
self.trial_ind += 1
self.saveState(out=self.backupFilepath)
def processResponse(self):
'''
'''
self.newResp = False
self.answers[self.trial_ind, self.q_ind] = self.answer in self.response
symb = symb_dict[self.answers[self.trial_ind, self.q_ind]]
self.socketio.emit('test_resp', {'q_ind': self.q_ind, 'trial_ind': self.trial_ind, "ans": symb}, namespace='/main')
def loadResponse(self):
incomplete_responses = np.isnan(self.answers).any(axis=1)[:, np.newaxis].repeat(2, axis=1)
self.answers[incomplete_responses] = np.nan
self.fillTable()
def finaliseResults(self):
toSave = ['marker_files', 'clinPageLoaded', 'wav_files', 'participant',
'response', 'backupFilepath', 'noise_path', 'question_files',
'si', 'question', 'answers', 'trial_ind']
saveDict = {k:self.__dict__[k] for k in toSave}
self.participant['eeg_test'].update(saveDict)
self.participant.save("eeg_test")
backup_path = os.path.join(self.participant.data_paths['eeg_test'],
'finalised_backup.pkl')
copy2(self.backupFilepath, backup_path)
self.finalised = True
def playStimulus(self, wav_file, replay=False):
@@ -96,14 +267,18 @@ class EEGMatTrainThread(BaseThread):
self.socketio.emit("stim_done", namespace="/main")
def loadStimulus(self):
def submitTestResponse(self, msg):
'''
Get and store participant response for current trial
'''
#audio, fs, enc, fmt = sndio.read(wav, return_format=True)
self.response = [x.upper() for x in msg['resp']]
self.newResp = True
def saveState(self, out="test_state.pkl"):
saveDict = {k:self.__dict__[k] for k in self.toSave}
def saveState(self, out="eeg_test_state.pkl"):
toSave = ['marker_files', 'wav_files', 'participant', 'response',
'backupFilepath', 'noise_path', 'question_files', 'si',
'question', 'answers', 'trial_ind']
saveDict = {k:self.__dict__[k] for k in toSave}
with open(out, 'wb') as f:
dill.dump(saveDict, f)
+3 -4
View File
@@ -1,7 +1,6 @@
from threading import Thread, Event
import os
import numpy as np
from matrix_test.filesystem import globDir
from pysndfile import PySndfile, sndio
from random import randint, shuffle
from shutil import copyfile
@@ -12,7 +11,8 @@ from shutil import copy2
from test_base import BaseThread
from matrix_test.signalops import play_wav
from matrix_test.helper_modules.signalops import play_wav
from matrix_test.helper_modules.filesystem import globDir
from scipy.special import logit
from config import socketio
import csv
@@ -65,11 +65,10 @@ class EEGStoryTrainThread(BaseThread):
self.socketio.on_event('finalise_results', self.finaliseResults, namespace='/main')
self.loadStimulus()
self.dev_mode = True
self.dev_mode = False
def setQuestion(self, q):
self.socketio.emit('set_question', data=q[0], namespace='/main')
set_trace()
def testLoop(self):
'''
+2 -2
View File
@@ -1,7 +1,7 @@
from threading import Thread, Event
import os
import numpy as np
from matrix_test.filesystem import globDir
from matrix_test.helper_modules.filesystem import globDir
from pysndfile import PySndfile, sndio
from random import randint, shuffle
from shutil import copyfile
@@ -47,7 +47,7 @@ class EEGTestThread(BaseThread):
Thread for running server side matrix test operations
'''
def __init__(self, sessionFilepath=None,
listFolder="./matrix_test/short_concat_stim/",
listFolder="./matrix_test/short_concat_stim/out",
noiseFilepath="./matrix_test/stimulus/wav/noise/noise.wav",
socketio=None, participant=None, srt_50=None, s_50=None):
self.noise_path = noiseFilepath
-1
View File
@@ -1 +0,0 @@
from .pathtype import PathType
@@ -22,7 +22,7 @@ from pathops import dir_must_exist
try:
from signalops import rolling_window_lastaxis, block_lfilter
except ImportError:
from .signalops import rolling_window_lastaxis, block_lfilter
from ..helper_modules.signalops import rolling_window_lastaxis, block_lfilter
import scipy.signal as sgnl
from scipy.stats import pearsonr
@@ -32,12 +32,12 @@ from pyswarm import pso
try:
from lpc import lpc
except ImportError:
from .lpc import lpc
from ..helper_modules.lpc import lpc
try:
from filesystem import globDir, organiseWavs, prepareOutDir
except ImportError:
from .filesystem import globDir, organiseWavs, prepareOutDir
from ..helper_modules.filesystem import globDir, organiseWavs, prepareOutDir
def synthesizeTrial(wavFileMatrix, indexes):
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
import sys
sys.path.insert(0, "../helper_modules/")
import csv
from tokens_to_words import tokens_to_words, load_component_map
import pdb
def main():
component_map_file = "../speech_components/component_map.json"
stim_parts = "./out/parts/stim_parts.csv"
stim_words = "./out/parts/stim_words.csv"
component_map = load_component_map(component_map_file)
lines = []
with open(stim_parts, 'r') as csvfile:
for line in csv.reader(csvfile):
lines.append(tokens_to_words(line, component_map))
with open(stim_words, 'w') as csvfile:
writer = csv.writer(csvfile)
writer.writerows(lines)
if __name__ == "__main__":
main()
+1 -1
View File
@@ -11,7 +11,7 @@ import csv
from shutil import copy2
from pysndfile import sndio, PySndfile
from matrix_test.filesystem import globDir
from matrix_test.helper_modules.filesystem import globDir
from test_base import BaseThread
import sounddevice as sd
import pdb
+1 -1
View File
@@ -21,7 +21,7 @@ from pysndfile import sndio
from scipy.optimize import minimize
from app import generate_matrix_stimulus
from matrix_test.filesystem import globDir, organiseWavs, prepareOutDir
from matrix_test.helper_modules.filesystem import globDir, organiseWavs, prepareOutDir
from matrix_test_thread import MatTestThread
from pathops import dir_must_exist
from participant import Participant, find_participants, gen_participant_num
+1 -1
View File
@@ -27,7 +27,7 @@ from pysndfile import sndio
from scipy.optimize import minimize
from app import generate_matrix_stimulus
from matrix_test.filesystem import globDir, organiseWavs, prepareOutDir
from matrix_test.helper_modules.filesystem import globDir, organiseWavs, prepareOutDir
from matrix_test_thread import MatTestThread
from pathops import dir_must_exist
from participant import Participant
+3 -3
View File
@@ -23,11 +23,11 @@ from scipy.optimize import minimize
from WavPlayer import play_wav_async
from app import generate_matrix_stimulus
from matrix_test.filesystem import globDir, organiseWavs, prepareOutDir
from matrix_test.helper_modules.filesystem import globDir, organiseWavs, prepareOutDir
from matrix_test_thread import MatTestThread
from pathops import dir_must_exist
from participant import Participant
from matrix_test.signalops import play_wav
from matrix_test.helper_modules.signalops import play_wav
from config import server, socketio, participants
@@ -126,13 +126,13 @@ def start_test(msg):
test_name = msg.pop('test_name')
part_key = msg.pop('part_key')
thread_type = thread_types[test_name]
socketio.emit('participant_start_{}'.format(test_name), namespace='/main')
if part_key != "--":
participant = participants[part_key]
else:
raise ValueError("Participant must be selected...")
socketio.emit('participant_start_{}'.format(test_name), namespace='/main')
socketio.emit('participant_start', test_name, namespace='/main', broadcast=True)
run_test_thread(test_name, thread_type, participant=participant, **msg)
+2 -1
View File
@@ -69,7 +69,8 @@
'eeg_test': "/eeg/test/run",
'da_test': "/da/run",
'click_test': "/click/run",
'eeg_story_train': "/eeg/train/story/run"
'eeg_story_train': "/eeg/train/story/run",
'eeg_mat_train': "/eeg/train/mat/run"
}
socket.on('participant_start', function(msg) {