diff --git a/examples/stimuli/advanced_video.py b/examples/stimuli/advanced_video.py index c2788aa6..781b6446 100644 --- a/examples/stimuli/advanced_video.py +++ b/examples/stimuli/advanced_video.py @@ -11,7 +11,7 @@ import numpy as np from expyfun import (ExperimentController, fetch_data_file, building_doc, - analyze as ea) + analyze as ea, visual) print(__doc__) @@ -26,22 +26,32 @@ with ExperimentController(**ec_args) as ec: screen_period = 1. / ec.estimate_screen_fs() all_presses = list() + fix = visual.FixationDot(ec) + text = text = visual.Text(ec, "Running ...", (0, -0.1), 'k') + screenshot = None # don't have one yet ec.load_video(movie_path) ec.video.set_scale('fill') ec.screen_prompt('press 1 during video to toggle pause.', max_wait=1.) ec.listen_presses() # to catch presses on first pass of while loop - t_zero = ec.video.play() - this_sec = 0 + t_zero = ec.video.play(auto_draw=False) + this_sec = 0. while not ec.video.finished: if ec.video.playing: - fliptime = ec.flip() - else: # to catch presses reliably, need delay between loop executions - ec.wait_secs(screen_period / 5) + ec.video.draw() + else: + ec.screen_text('paused!', color='y', font_size=32, wrap=False) + text.draw() + fix.draw() + if screenshot is None: + screenshot = ec.screenshot() + fliptime = ec.flip() presses = ec.get_presses(live_keys=[1], relative_to=t_zero) ec.listen_presses() # change the background color every 1 second if this_sec != int(ec.video.time): this_sec = int(ec.video.time) + text = visual.Text( + ec, str(colors[this_sec]), (0, -0.1), 'k') ec.set_background_color(colors[this_sec]) # shrink the video, then move it rightward if ec.video.playing: @@ -54,15 +64,9 @@ all_presses.extend(presses) if len(presses) % 2: # if even number of presses, do nothing if ec.video.playing: - ec.video.set_visible(False) ec.video.pause() - ec.screen_text('pause!', color='k', font_size=32, - wrap=False) - ec.flip() else: - ec.video.set_visible(True) - ec.video.play() - screenshot = ec.screenshot() + ec.video.play(auto_draw=False) if building_doc: break ec.delete_video() diff --git a/expyfun/_experiment_controller.py b/expyfun/_experiment_controller.py index 8f18c6fb..23fa276e 100644 --- a/expyfun/_experiment_controller.py +++ b/expyfun/_experiment_controller.py @@ -1775,7 +1775,7 @@ def _validate_audio(self, samples): samples = np.asarray(samples, dtype=np.float32) # check values - if np.max(np.abs(samples)) > 1: + if samples.size and np.max(np.abs(samples)) > 1: raise ValueError('Sound data exceeds +/- 1.') # samples /= np.max(np.abs(samples),axis=0) @@ -1795,12 +1795,13 @@ def _validate_audio(self, samples): logger.warning('Expyfun: Resampling {} seconds of audio' ''.format(round(len(samples) / self.stim_fs, 2))) from mne.filter import resample - samples = resample( - samples.astype(np.float64), self.fs, self.stim_fs, - axis=0).astype(np.float32) + if samples.size: + samples = resample( + samples.astype(np.float64), self.fs, self.stim_fs, + axis=0).astype(np.float32) # check RMS - if self._check_rms is not None: + if self._check_rms is not None and samples.size: chans = [samples[:, x] for x in range(samples.shape[1])] if self._check_rms == 'wholefile': chan_rms = [np.sqrt(np.mean(x ** 2)) for x in chans] diff --git a/expyfun/_eyelink_controller.py b/expyfun/_eyelink_controller.py index 43c34f0f..57ae2872 100644 --- a/expyfun/_eyelink_controller.py +++ b/expyfun/_eyelink_controller.py @@ -779,7 +779,12 @@ def on_key_press(symbol, modifiers): on_mouse_drag) def release_event_handlers(self): - self.ec.window.pop_handlers() # should detacch top-level handler + try: + fun = self.ec.window.pop_handlers + except AttributeError: + pass # Pyglet bug? + else: + fun() # should detach top-level handler del self.label del self.img diff --git a/expyfun/tests/test_experiment_controller.py b/expyfun/tests/test_experiment_controller.py index 13c158c0..69130151 100644 --- a/expyfun/tests/test_experiment_controller.py +++ b/expyfun/tests/test_experiment_controller.py @@ -235,6 +235,7 @@ def test_ec(ac, hide_window): # test buffer data handling ec.set_rms_checking(None) ec.load_buffer([0, 0, 0, 0, 0, 0]) + ec.load_buffer([]) pytest.raises(ValueError, ec.load_buffer, [0, 2, 0, 0, 0, 0]) ec.load_buffer(np.zeros((100,))) with pytest.raises(ValueError, match='100 did not match .* count 2'): diff --git a/expyfun/visual/_visual.py b/expyfun/visual/_visual.py index 3ec97d8a..4804612b 100644 --- a/expyfun/visual/_visual.py +++ b/expyfun/visual/_visual.py @@ -105,7 +105,8 @@ def __init__(self, ec, text, pos=(0, 0), color='white', elif isinstance(width, string_types): raise ValueError('"width", if str, must be "auto"') self._attr = attr - text = text + '\n ' # weird Pyglet bug + if wrap: + text = text + '\n ' # weird Pyglet bug if self._attr: preamble = ('{{font_name \'{}\'}}{{font_size {}}}{{color {}}}' '').format(font_name, font_size, _convert_color(color)) @@ -320,7 +321,7 @@ def set_line_width(self, line_width): self._line_width = line_width def draw(self): - """Draw the object to the display buffer""" + """Draw the object to the display buffer.""" gl.glUseProgram(self._program) for kind in ('fill', 'line'): if self._counts[kind] > 0: @@ -796,7 +797,7 @@ def set_color(self, color, idx): self._circles[idx].set_fill_color(color) def set_colors(self, colors): - """Set the color of each circle + """Set the color of each circle. Parameters ---------- @@ -811,8 +812,7 @@ def set_colors(self, colors): self.set_color(color, idx) def draw(self): - """Draw the fixation dot - """ + """Draw the fixation dot.""" for circle in self._circles: circle.draw() @@ -1112,9 +1112,14 @@ def __init__(self, ec, file_name, pos=(0, 0), units='norm', scale=1., self._visible = visible self._eos_fun = self._eos_new if _new_pyglet() else self._eos_old - def play(self): + def play(self, auto_draw=True): """Play video from current position. + Parameters + ---------- + auto_draw : bool + If True, add ``self.draw`` to ``ec.on_every_flip``. + Returns ------- time : float @@ -1122,7 +1127,8 @@ def play(self): which ``play()`` was called. """ if not self._playing: - self._ec.call_on_every_flip(self.draw) + if auto_draw: + self._ec.call_on_every_flip(self.draw) self._player.play() self._playing = True else: @@ -1140,8 +1146,12 @@ def pause(self): which ``pause()`` was called. """ if self._playing: - idx = self._ec.on_every_flip_functions.index(self.draw) - self._ec.on_every_flip_functions.pop(idx) + try: + idx = self._ec.on_every_flip_functions.index(self.draw) + except ValueError: # not auto_draw + pass + else: + self._ec.on_every_flip_functions.pop(idx) self._player.pause() self._playing = False else: @@ -1216,6 +1226,7 @@ def set_pos(self, pos, units='norm', center=True): def _draw(self): self._texture = self._player.get_texture() self._scale_texture() + gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0) self._texture.blit(*self._actual_pos) def draw(self):