add option for automatic run. rename open display of condition names to A and B

parent c2361d31
...@@ -46,7 +46,7 @@ from sp_experiment.define_payoff_settings import (get_payoff_settings, ...@@ -46,7 +46,7 @@ from sp_experiment.define_payoff_settings import (get_payoff_settings,
from sp_experiment.define_ttl_triggers import provide_trigger_dict from sp_experiment.define_ttl_triggers import provide_trigger_dict
def navigation(): def navigation(nav='initial', bonus=''):
"""Lead through a navigation GUI. """Lead through a navigation GUI.
Provides the options to run the experiment, test trials, or print out the Provides the options to run the experiment, test trials, or print out the
...@@ -54,23 +54,30 @@ def navigation(): ...@@ -54,23 +54,30 @@ def navigation():
it either starts the test trials and quits, or prints the bonus money and it either starts the test trials and quits, or prints the bonus money and
quits. quits.
Parameters
----------
nav : str
Entry point into the navigation. Can be 'initial' or 'show_bonus'
bonus : str
Specify the bonus to be shown.
Returns Returns
------- -------
run : bool run : bool
""" """
run = False run = False
nav = 'initial' auto = False
bonus = ''
while not nav == 'finished': while not nav == 'finished':
# Prepare GUI # Prepare GUI
myDlg = gui.Dlg(title='Sampling Paradigm Experiment') myDlg = gui.Dlg(title='Sampling Paradigm Experiment')
if nav == 'initial': if nav == 'initial':
myDlg.addField('What to do?:', choices=['run experiment', myDlg.addField('What to do?:', choices=['automatic run',
'run experiment',
'run test trials', 'run test trials',
'calculate bonus money']) 'calculate bonus money'])
elif nav == 'testing_cond': elif nav == 'testing_cond':
myDlg.addField('Condition:', choices=['active', 'passive']) myDlg.addField('Condition:', choices=['A', 'B'])
elif nav == 'calc_bonus': elif nav == 'calc_bonus':
myDlg.addField('ID:', choices=list(range(1, 21))) myDlg.addField('ID:', choices=list(range(1, 21)))
...@@ -82,7 +89,12 @@ def navigation(): ...@@ -82,7 +89,12 @@ def navigation():
# Get data # Get data
ok_data = myDlg.show() ok_data = myDlg.show()
if myDlg.OK: if myDlg.OK:
if ok_data[0] == 'run experiment': if ok_data[0] == 'automatic run':
print('auto run experiment')
run = True
auto = True
nav = 'finished'
elif ok_data[0] == 'run experiment':
print('running experiment now') print('running experiment now')
run = True run = True
nav = 'finished' # quit navigattion and run experiment nav = 'finished' # quit navigattion and run experiment
...@@ -91,7 +103,8 @@ def navigation(): ...@@ -91,7 +103,8 @@ def navigation():
elif nav == 'testing_cond': elif nav == 'testing_cond':
print('preparing test trials now') print('preparing test trials now')
# run test trials, then quit program # run test trials, then quit program
run_test_trials(condition=ok_data[0]) condition = 'active' if ok_data[0] == 'A' else 'passive'
run_test_trials(condition=condition)
core.quit() core.quit()
elif ok_data[0] == 'calculate bonus money': elif ok_data[0] == 'calculate bonus money':
nav = 'calc_bonus' # ask for ID nav = 'calc_bonus' # ask for ID
...@@ -104,10 +117,10 @@ def navigation(): ...@@ -104,10 +117,10 @@ def navigation():
print('user cancelled GUI input') print('user cancelled GUI input')
core.quit() core.quit()
return run return run, auto
def prep_logging(yoke_map): def prep_logging(yoke_map, gui_info=None):
"""Prepare logging for the experiment run. """Prepare logging for the experiment run.
Parameters Parameters
...@@ -117,30 +130,38 @@ def prep_logging(yoke_map): ...@@ -117,30 +130,38 @@ def prep_logging(yoke_map):
active task. That task will then be served as a replay to the current active task. That task will then be served as a replay to the current
ID. ID.
gui_info : dict
Returns Returns
------- -------
data_file : str data_file : str
path to the data file path to the data file
""" """
# Collect the ID, age, sex, condition if not isinstance(gui_info, dict):
myDlg = gui.Dlg(title='Sampling Paradigm Experiment') # Collect the ID, age, sex, condition
myDlg.addField('ID:', choices=list(range(1, 21))) myDlg = gui.Dlg(title='Sampling Paradigm Experiment')
myDlg.addField('Age:', choices=list(range(18, 100))) myDlg.addField('ID:', choices=list(range(1, 21)))
myDlg.addField('Sex:', choices=['Male', 'Female']) myDlg.addField('Age:', choices=list(range(18, 100)))
myDlg.addField('Condition:', choices=['active', 'passive']) myDlg.addField('Sex:', choices=['Male', 'Female'])
myDlg.addField('Condition:', choices=['A', 'B'])
# show dialog and wait for OK or Cancel
ok_data = myDlg.show() # show dialog and wait for OK or Cancel
if myDlg.OK: # or if ok_data is not None ok_data = myDlg.show()
sub_id = int(ok_data[0]) if myDlg.OK: # or if ok_data is not None
age = int(ok_data[1]) sub_id = int(ok_data[0])
sex = ok_data[2] age = int(ok_data[1])
condition = ok_data[3] sex = ok_data[2]
yoke_to = yoke_map[sub_id] condition = 'active' if ok_data[3] == 'A' else 'passive'
yoke_to = yoke_map[sub_id]
else:
print('user cancelled GUI input')
core.quit()
else: else:
print('user cancelled GUI input') sub_id = gui_info['sub_id']
core.quit() condition = gui_info['condition2']
yoke_to = yoke_map[sub_id]
# Data logging # Data logging
# ============ # ============
...@@ -151,8 +172,7 @@ def prep_logging(yoke_map): ...@@ -151,8 +172,7 @@ def prep_logging(yoke_map):
data_file = op.join(data_dir, fname) data_file = op.join(data_dir, fname)
if op.exists(data_file): if op.exists(data_file):
raise OSError(f'A data file for {sub_id} ' raise OSError(f'\n\nA data file for ID "{sub_id}" already exists.\n\n')
f'already exists: {data_file}')
# Write header to the tab separated log file # Write header to the tab separated log file
variable_meanings_dict = make_events_json_dict() variable_meanings_dict = make_events_json_dict()
...@@ -162,15 +182,19 @@ def prep_logging(yoke_map): ...@@ -162,15 +182,19 @@ def prep_logging(yoke_map):
header = '\t'.join(variables) header = '\t'.join(variables)
fout.write(header + '\n') fout.write(header + '\n')
# Write a brief log file for this participant # Write a brief log file for this participant ... only needs to be done
fname = f'log_{sub_id}_{condition}.txt' # once. If it is done twice, then you can check which condition was first
log_path = op.join(data_dir, fname) # by checking the starting time in the events.tsv file.
with open(log_path, 'w') as fout: if not isinstance(gui_info, dict):
for line in [sub_id, age, sex, condition, yoke_to]: fname = f'log_{sub_id}_{condition}.txt'
fout.write(f'{line}') # noqa E999 log_path = op.join(data_dir, fname)
fout.write('\n') prefixes = ['sub_id', 'age', 'sex', 'yoke_to']
with open(log_path, 'w') as fout:
for i, line in enumerate([sub_id, age, sex, yoke_to]):
fout.write(f'{prefixes[i]}: {line}')
fout.write('\n')
return data_file, condition, yoke_to return sub_id, data_file, condition, yoke_to
def run_flow(monitor='testMonitor', ser=Fake_serial(), max_ntrls=10, def run_flow(monitor='testMonitor', ser=Fake_serial(), max_ntrls=10,
...@@ -277,7 +301,8 @@ def run_flow(monitor='testMonitor', ser=Fake_serial(), max_ntrls=10, ...@@ -277,7 +301,8 @@ def run_flow(monitor='testMonitor', ser=Fake_serial(), max_ntrls=10,
# =========================== # ===========================
# Get ready to start the experiment. Start timing from next button press. # Get ready to start the experiment. Start timing from next button press.
modstr = 'experiment' if not is_test else 'TEST TRIAL' modstr = 'experiment' if not is_test else 'TEST TRIAL'
txt_stim.text = (f'Starting the {modstr} in {condition} condition! ' modstr_cond = 'A' if condition == 'active' else 'B'
txt_stim.text = (f'Starting the {modstr} for task {modstr_cond}! '
'Press any key to start.') 'Press any key to start.')
txt_stim.height = 1 txt_stim.height = 1
txt_stim.font = font txt_stim.font = font
...@@ -728,17 +753,74 @@ if __name__ == '__main__': ...@@ -728,17 +753,74 @@ if __name__ == '__main__':
for i, j in zip(list(range(11, 21)), list(range(1, 11))): for i, j in zip(list(range(11, 21)), list(range(1, 11))):
yoke_map[i] = j yoke_map[i] = j
# experiment settings
monitor = 'eizoforis'
ser = Fake_serial()
max_ntrls = 75
max_nsamples = 12
block_size = 25
# Navigate # Navigate
run = navigation() run, auto = navigation()
if run:
data_file, condition, yoke_to = prep_logging(yoke_map) # Perhaps just run (no auto)
run_flow(monitor='eizoforis', if run and not auto:
ser=Fake_serial(), sub_id, data_file, condition, yoke_to = prep_logging(yoke_map)
max_ntrls=75, run_flow(monitor=monitor,
max_nsamples=12, ser=ser,
block_size=25, max_ntrls=max_ntrls,
max_nsamples=max_nsamples,
block_size=block_size,
data_file=data_file, data_file=data_file,
condition=condition, condition=condition,
yoke_to=yoke_to) yoke_to=yoke_to)
# if auto, do a complete flow
if run and auto:
# Get input
sub_id, data_file, condition, yoke_to = prep_logging(yoke_map)
# Save for later
info = dict()
info['sub_id'] = sub_id
# Run test for first condition
if condition == 'active':
run_test_trials(monitor=monitor, condition=condition)
info['condition2'] = 'passive'
elif condition == 'passive':
run_test_trials(monitor=monitor, condition=condition)
info['condition2'] = 'active'
# Run first condition
run_flow(monitor=monitor,
ser=ser,
max_ntrls=max_ntrls,
max_nsamples=max_nsamples,
block_size=block_size,
data_file=data_file,
condition=condition,
yoke_to=yoke_to)
# Run test for second condition
run_test_trials(monitor=monitor, condition=info['condition2'])
# prep new data_file, skipping GUI
sub_id, data_file, condition, yoke_to = prep_logging(yoke_map,
gui_info=info)
# Run second condition
run_flow(monitor=monitor,
ser=ser,
max_ntrls=max_ntrls,
max_nsamples=max_nsamples,
block_size=block_size,
data_file=data_file,
condition=condition,
yoke_to=yoke_to)
# Print out earnings
bonus = calc_bonus_payoff(sub_id)
navigation(nav='show_bonus', bonus=bonus)
core.quit() core.quit()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment