Added stim_part to word csv converter script
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
+201
-26
@@ -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,
|
||||
sessionFilepath=sessionFilepath,
|
||||
socketio=socketio,
|
||||
participant=participant)
|
||||
|
||||
self.toSave = ['trial_ind', 'nTrials', 'wav_file', 'test_name']
|
||||
super(EEGMatTrainThread, self).__init__('eeg_mat_train',
|
||||
sessionFilepath=sessionFilepath,
|
||||
socketio=socketio,
|
||||
participant=participant)
|
||||
|
||||
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.saveState(out=self.backupFilepath)
|
||||
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)
|
||||
|
||||
@@ -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
@@ -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 +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
@@ -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()
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user