From ae3bc8743a069bc3e61b578a21b132d6ac97f9b3 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Tue, 8 Apr 2014 10:04:51 -0700 Subject: [PATCH] ENH: Change to start_stimulus --- examples/eyetracking_experiment.py | 2 +- examples/simple_experiment.py | 4 +-- examples/sync_test.py | 2 +- expyfun/_experiment_controller.py | 37 +++++++++++++-------- expyfun/_trigger_controllers.py | 2 +- expyfun/codeblocks/_pupillometry.py | 4 +-- expyfun/tests/test_experiment_controller.py | 12 +++---- expyfun/tests/test_eyelink_controller.py | 4 +-- 8 files changed, 38 insertions(+), 29 deletions(-) diff --git a/examples/eyetracking_experiment.py b/examples/eyetracking_experiment.py index b568607d..95868ca5 100644 --- a/examples/eyetracking_experiment.py +++ b/examples/eyetracking_experiment.py @@ -46,7 +46,7 @@ targ_circ.draw() screenshot = ec.screenshot() ec.identify_trial(ec_id='Circle', ttl_id=[0], el_id=[0]) - ec.flip_and_play() # automatically stamps to EL + ec.start_stimulus() # automatically stamps to EL if not el.wait_for_fix(fix_pos, 1., max_wait=5., units='deg'): print('Initial fixation failed') for ii, (x, y) in enumerate(zip(x_pos[1:], y_pos[1:])): diff --git a/examples/simple_experiment.py b/examples/simple_experiment.py index 99f16f60..06cd9ffa 100644 --- a/examples/simple_experiment.py +++ b/examples/simple_experiment.py @@ -113,7 +113,7 @@ ec.clear_buffer() ec.load_buffer(wavs[stim_num]) ec.identify_trial(ec_id=stim_num, ttl_id=[0, 0]) - ec.flip_and_play() + ec.start_stimulus() pressed, timestamp = ec.wait_one_press(max_resp_time, min_resp_time, live_keys) ec.stop() # will stop stim playback as soon as response logged @@ -149,7 +149,7 @@ ec.load_buffer(concat_wavs) ec.write_data_line('multi-tone trial', [x + 1 for x in mass_trial_order]) ec.identify_trial(ec_id='multi-tone', ttl_id=[0, 1]) - ec.flip_and_play() + ec.start_stimulus() ec.wait_secs(len(concat_wavs) / float(ec.stim_fs)) ec.screen_text('
Go!
') ec.flip() diff --git a/examples/sync_test.py b/examples/sync_test.py index 8180a815..474fb4d9 100644 --- a/examples/sync_test.py +++ b/examples/sync_test.py @@ -38,7 +38,7 @@ screenshot = None while pressed != '8': # enable a clean quit if required ec.draw_background_color('white') - t1 = ec.flip_and_play(start_of_trial=False) # skip checks + t1 = ec.start_stimulus(start_of_trial=False) # skip checks ec.draw_background_color('black') t2 = ec.flip() diff = round(1000 * (t2 - t1), 2) diff --git a/expyfun/_experiment_controller.py b/expyfun/_experiment_controller.py index 9558b1d0..37a88813 100644 --- a/expyfun/_experiment_controller.py +++ b/expyfun/_experiment_controller.py @@ -460,8 +460,8 @@ def draw_background_color(self, color='black'): rect.draw() return rect - def flip_and_play(self, start_of_trial=True): - """Flip screen, play audio, then run any "on-flip" functions. + def start_stimulus(self, start_of_trial=True, flip=True): + """Play audio, (optionally) flip screen, run any "on_flip" functions. Parameters ---------- @@ -469,6 +469,8 @@ def flip_and_play(self, start_of_trial=True): If True, it checks to make sure that the trial ID has been stamped appropriately. Set to False only in cases where ``flip_and_play`` is to be used mid-trial (should be rare!). + flip : bool + If False, don't flip the screen. Returns ------- @@ -477,22 +479,30 @@ def flip_and_play(self, start_of_trial=True): Notes ----- - Order of operations is: screen flip, audio start, additional functions - added with ``on_next_flip``, followed by functions added with - ``on_every_flip``. + Order of operations is: screen flip (optional), audio start, then + (only if ``flip=True``) additional functions added with + ``on_next_flip`` and ``on_every_flip``. """ if start_of_trial: if not self._trial_identified: raise RuntimeError('Trial ID must be stamped before starting ' 'the trial') self._trial_identified = False - logger.exp('Expyfun: Flipping screen and playing audio') + extra = 'flipping screen and ' if flip else '' + logger.exp('Expyfun: Starting stimuli: {0}playing audio'.format(extra)) # ensure self._play comes first in list, followed by other critical # private functions (e.g., EL stamping), then user functions: - self._on_next_flip = ([self._play] + self._ofp_critical_funs + - self._on_next_flip) - flip_time = self.flip() - return flip_time + if flip: + self._on_next_flip = ([self._play] + self._ofp_critical_funs + + self._on_next_flip) + stimulus_time = self.flip() + else: + funs = [self._play] + self._ofp_critical_funs + self._win.dispatch_events() + stimulus_time = self._clock.get_time() + for fun in funs: + fun() + return stimulus_time def play(self): """Start audio playback @@ -733,9 +743,8 @@ def flip(self): Notes ----- - Order of operations is: screen flip, audio start, additional functions - added with ``on_every_flip``, followed by functions added with - ``on_next_flip``. + Order of operations is: screen flip, functions added with + ``on_next_flip``, followed by functions added with ``on_every_flip``. """ call_list = self._on_next_flip + self._on_every_flip self._win.dispatch_events() @@ -964,8 +973,8 @@ def load_buffer(self, samples): def _play(self): """Play the audio buffer. """ - logger.debug('Expyfun: playing audio') self._ac.play() + logger.debug('Expyfun: started audio') self.write_data_line('play') def stop(self): diff --git a/expyfun/_trigger_controllers.py b/expyfun/_trigger_controllers.py index f440c56b..f078f758 100644 --- a/expyfun/_trigger_controllers.py +++ b/expyfun/_trigger_controllers.py @@ -15,7 +15,7 @@ class ParallelTrigger(object): """Parallel port and dummy triggering support IMPORTANT: When using the parallel port, note that calling - ec.flip_and_play() will automatically invoke a stamping of + ec.start_stimulus() will automatically invoke a stamping of the 1 trigger, which will cause a delay equal to that of high_duration. diff --git a/expyfun/codeblocks/_pupillometry.py b/expyfun/codeblocks/_pupillometry.py index 9790dd70..ac7b7d08 100644 --- a/expyfun/codeblocks/_pupillometry.py +++ b/expyfun/codeblocks/_pupillometry.py @@ -97,7 +97,7 @@ def find_pupil_dynamic_range(ec, el, prompt=True, verbose=None): bgrect.set_fill_color(np.ones(3) * lev) bgrect.draw() fix.draw() - ec.flip_and_play() + ec.start_stimulus() ec.wait_secs(settle_time) ec.check_force_quit() ec.trial_ok() @@ -233,7 +233,7 @@ def find_pupil_tone_impulse_response(ec, el, bgcolor, prompt=True, ec.load_buffer(sweep_stim if targ else tone_stim) ec.identify_trial(ec_id='TONE_{0}'.format(int(targ)), el_id=[int(targ)], ttl_id=[int(targ)]) - flip_times.append(ec.flip_and_play()) + flip_times.append(ec.start_stimulus()) presses.append(ec.wait_for_presses(isi)) ec.stop() ec.trial_ok() diff --git a/expyfun/tests/test_experiment_controller.py b/expyfun/tests/test_experiment_controller.py index 06fc0a8f..7ad3518d 100644 --- a/expyfun/tests/test_experiment_controller.py +++ b/expyfun/tests/test_experiment_controller.py @@ -214,24 +214,24 @@ def test_ec(ac=None, rd=None): assert_equal(len(w), 3) ec.stop() - ec.call_on_every_flip(dummy_print, 'called on flip and play') - assert_raises(RuntimeError, ec.flip_and_play) - ec.flip_and_play(start_of_trial=False) # should work + ec.call_on_every_flip(dummy_print, 'called start stimuli') + assert_raises(RuntimeError, ec.start_stimulus) + ec.start_stimulus(start_of_trial=False) # should work assert_raises(KeyError, ec.identify_trial, ec_id='foo') # need ttl_id # only binary for TTL assert_raises(TypeError, ec.identify_trial, ec_id='foo', ttl_id='bar') assert_raises(ValueError, ec.identify_trial, ec_id='foo', ttl_id=[2]) ec.identify_trial(ec_id='foo', ttl_id=[0, 1]) assert_raises(RuntimeError, ec.identify_trial, ec_id='foo', ttl_id=[0]) - ec.flip_and_play() + ec.start_stimulus(flip=False) ec.flip() ec.estimate_screen_fs() ec.play() ec.call_on_every_flip(None) ec.call_on_next_flip(ec.start_noise()) - ec.flip_and_play(start_of_trial=False) + ec.start_stimulus(start_of_trial=False) ec.call_on_next_flip(ec.stop_noise()) - ec.flip_and_play(start_of_trial=False) + ec.start_stimulus(start_of_trial=False) ec.get_mouse_position() ec.toggle_cursor(False) ec.toggle_cursor(True, True) diff --git a/expyfun/tests/test_eyelink_controller.py b/expyfun/tests/test_eyelink_controller.py index 524f50b5..ece8da49 100644 --- a/expyfun/tests/test_eyelink_controller.py +++ b/expyfun/tests/test_eyelink_controller.py @@ -38,9 +38,9 @@ def test_eyelink_methods(): # missing el_id assert_raises(KeyError, ec.identify_trial, ec_id='foo', ttl_id=[0]) ec.identify_trial(ec_id='foo', ttl_id=[0], el_id=[1]) - ec.flip_and_play() + ec.start_stimulus() ec.identify_trial(ec_id='foo', ttl_id=[0], el_id=[1, 1]) - ec.flip_and_play() + ec.start_stimulus() assert_raises(ValueError, ec.identify_trial, ec_id='foo', ttl_id=[0], el_id=[1, dict()]) assert_raises(ValueError, ec.identify_trial, ec_id='foo', ttl_id=[0],