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 pathops
import os import os
from matrix_test.generate_matrix_stimulus import generateAudioStimulus from matrix_test.long_concat_stim.gen_long_stim import generateAudioStimulus
import time import time
import config import config
+2 -2
View File
@@ -1,7 +1,7 @@
from threading import Thread, Event from threading import Thread, Event
import os import os
import numpy as np import numpy as np
from matrix_test.filesystem import globDir from matrix_test.helper_modules.filesystem import globDir
from pysndfile import PySndfile, sndio from pysndfile import PySndfile, sndio
from random import randint, shuffle from random import randint, shuffle
from shutil import copyfile from shutil import copyfile
@@ -12,7 +12,7 @@ from shutil import copy2
from test_base import BaseThread 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 scipy.special import logit
from config import socketio from config import socketio
import csv import csv
+2 -2
View File
@@ -1,7 +1,7 @@
from threading import Thread, Event from threading import Thread, Event
import os import os
import numpy as np import numpy as np
from matrix_test.filesystem import globDir from matrix_test.helper_modules.filesystem import globDir
from pysndfile import PySndfile, sndio from pysndfile import PySndfile, sndio
from random import randint, shuffle from random import randint, shuffle
from shutil import copyfile from shutil import copyfile
@@ -12,7 +12,7 @@ from shutil import copy2
from test_base import BaseThread 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 scipy.special import logit
from config import socketio from config import socketio
import csv import csv
+201 -26
View File
@@ -1,7 +1,7 @@
from threading import Thread, Event from threading import Thread, Event
import os import os
import numpy as np import numpy as np
from matrix_test.filesystem import globDir from matrix_test.helper_modules.filesystem import globDir
from pysndfile import PySndfile, sndio from pysndfile import PySndfile, sndio
from random import randint, shuffle from random import randint, shuffle
from shutil import copyfile from shutil import copyfile
@@ -10,9 +10,7 @@ import numpy as np
import pandas as pd import pandas as pd
from shutil import copy2 from shutil import copy2
from test_base import BaseThread from test_base import BaseThread, run_test_thread
from matrix_test.signalops import play_wav
from scipy.special import logit from scipy.special import logit
from config import socketio from config import socketio
import csv import csv
@@ -24,6 +22,17 @@ symb_dict = {
False: 10007 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(): def set_trace():
import logging import logging
log = logging.getLogger('werkzeug') log = logging.getLogger('werkzeug')
@@ -38,25 +47,128 @@ class EEGMatTrainThread(BaseThread):
Thread for running server side matrix test operations Thread for running server side matrix test operations
''' '''
def __init__(self, sessionFilepath=None, 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): 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.wav_files = []
self.nTrials = nTrials 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.trial_ind = 0
self._stopevent = Event() self._stopevent = Event()
super(DaTestThread, self).__init__(self.test_name, super(EEGMatTrainThread, self).__init__('eeg_mat_train',
sessionFilepath=sessionFilepath, sessionFilepath=sessionFilepath,
socketio=socketio, socketio=socketio,
participant=participant) 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.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): def testLoop(self):
@@ -64,22 +176,81 @@ class EEGMatTrainThread(BaseThread):
Main loop for iteratively finding the SRT Main loop for iteratively finding the SRT
''' '''
self.waitForPageLoad() self.waitForPageLoad()
self.socketio.emit('test_ready', namespace='/main') self.loadResponse()
for self.trial_ind in range(self.nTrials): 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.displayInstructions()
self.waitForPartReady() self.waitForPartReady()
if self._stopevent.isSet() or self.finishTest: if self._stopevent.isSet() or self.finishTest:
break break
# Play concatenated matrix sentences at set SNR # Play concatenated matrix sentences at set SNR
self.playStimulus(self.wav_file) self.playStimulus(wav)
self.saveState(out=self.backupFilepath) self.setMatrix(q)
self.saveState(out=self.backupFilepath)
if not self._stopevent.isSet(): if not self._stopevent.isSet():
self.unsetPageLoaded() self.unsetPageLoaded()
self.socketio.emit('processing-complete', namespace='/main') self.socketio.emit('processing-complete', namespace='/main')
self.waitForPageLoad()
self.fillTable()
def displayInstructions(self): 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): def playStimulus(self, wav_file, replay=False):
@@ -96,14 +267,18 @@ class EEGMatTrainThread(BaseThread):
self.socketio.emit("stim_done", namespace="/main") self.socketio.emit("stim_done", namespace="/main")
def submitTestResponse(self, msg):
def loadStimulus(self):
''' '''
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"): def saveState(self, out="eeg_test_state.pkl"):
saveDict = {k:self.__dict__[k] for k in self.toSave} 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: with open(out, 'wb') as f:
dill.dump(saveDict, f) dill.dump(saveDict, f)
+3 -4
View File
@@ -1,7 +1,6 @@
from threading import Thread, Event from threading import Thread, Event
import os import os
import numpy as np import numpy as np
from matrix_test.filesystem import globDir
from pysndfile import PySndfile, sndio from pysndfile import PySndfile, sndio
from random import randint, shuffle from random import randint, shuffle
from shutil import copyfile from shutil import copyfile
@@ -12,7 +11,8 @@ from shutil import copy2
from test_base import BaseThread 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 scipy.special import logit
from config import socketio from config import socketio
import csv import csv
@@ -65,11 +65,10 @@ class EEGStoryTrainThread(BaseThread):
self.socketio.on_event('finalise_results', self.finaliseResults, namespace='/main') self.socketio.on_event('finalise_results', self.finaliseResults, namespace='/main')
self.loadStimulus() self.loadStimulus()
self.dev_mode = True self.dev_mode = False
def setQuestion(self, q): def setQuestion(self, q):
self.socketio.emit('set_question', data=q[0], namespace='/main') self.socketio.emit('set_question', data=q[0], namespace='/main')
set_trace()
def testLoop(self): def testLoop(self):
''' '''
+2 -2
View File
@@ -1,7 +1,7 @@
from threading import Thread, Event from threading import Thread, Event
import os import os
import numpy as np import numpy as np
from matrix_test.filesystem import globDir from matrix_test.helper_modules.filesystem import globDir
from pysndfile import PySndfile, sndio from pysndfile import PySndfile, sndio
from random import randint, shuffle from random import randint, shuffle
from shutil import copyfile from shutil import copyfile
@@ -47,7 +47,7 @@ class EEGTestThread(BaseThread):
Thread for running server side matrix test operations Thread for running server side matrix test operations
''' '''
def __init__(self, sessionFilepath=None, 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", noiseFilepath="./matrix_test/stimulus/wav/noise/noise.wav",
socketio=None, participant=None, srt_50=None, s_50=None): socketio=None, participant=None, srt_50=None, s_50=None):
self.noise_path = noiseFilepath 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: try:
from signalops import rolling_window_lastaxis, block_lfilter from signalops import rolling_window_lastaxis, block_lfilter
except ImportError: 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 import scipy.signal as sgnl
from scipy.stats import pearsonr from scipy.stats import pearsonr
@@ -32,12 +32,12 @@ from pyswarm import pso
try: try:
from lpc import lpc from lpc import lpc
except ImportError: except ImportError:
from .lpc import lpc from ..helper_modules.lpc import lpc
try: try:
from filesystem import globDir, organiseWavs, prepareOutDir from filesystem import globDir, organiseWavs, prepareOutDir
except ImportError: except ImportError:
from .filesystem import globDir, organiseWavs, prepareOutDir from ..helper_modules.filesystem import globDir, organiseWavs, prepareOutDir
def synthesizeTrial(wavFileMatrix, indexes): 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 shutil import copy2
from pysndfile import sndio, PySndfile from pysndfile import sndio, PySndfile
from matrix_test.filesystem import globDir from matrix_test.helper_modules.filesystem import globDir
from test_base import BaseThread from test_base import BaseThread
import sounddevice as sd import sounddevice as sd
import pdb import pdb
+1 -1
View File
@@ -21,7 +21,7 @@ from pysndfile import sndio
from scipy.optimize import minimize from scipy.optimize import minimize
from app import generate_matrix_stimulus 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 matrix_test_thread import MatTestThread
from pathops import dir_must_exist from pathops import dir_must_exist
from participant import Participant, find_participants, gen_participant_num 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 scipy.optimize import minimize
from app import generate_matrix_stimulus 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 matrix_test_thread import MatTestThread
from pathops import dir_must_exist from pathops import dir_must_exist
from participant import Participant from participant import Participant
+3 -3
View File
@@ -23,11 +23,11 @@ from scipy.optimize import minimize
from WavPlayer import play_wav_async from WavPlayer import play_wav_async
from app import generate_matrix_stimulus 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 matrix_test_thread import MatTestThread
from pathops import dir_must_exist from pathops import dir_must_exist
from participant import Participant 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 from config import server, socketio, participants
@@ -126,13 +126,13 @@ def start_test(msg):
test_name = msg.pop('test_name') test_name = msg.pop('test_name')
part_key = msg.pop('part_key') part_key = msg.pop('part_key')
thread_type = thread_types[test_name] thread_type = thread_types[test_name]
socketio.emit('participant_start_{}'.format(test_name), namespace='/main')
if part_key != "--": if part_key != "--":
participant = participants[part_key] participant = participants[part_key]
else: else:
raise ValueError("Participant must be selected...") 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) socketio.emit('participant_start', test_name, namespace='/main', broadcast=True)
run_test_thread(test_name, thread_type, participant=participant, **msg) run_test_thread(test_name, thread_type, participant=participant, **msg)
+2 -1
View File
@@ -69,7 +69,8 @@
'eeg_test': "/eeg/test/run", 'eeg_test': "/eeg/test/run",
'da_test': "/da/run", 'da_test': "/da/run",
'click_test': "/click/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) { socket.on('participant_start', function(msg) {