Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Fix video playback with other visuals #413

Merged
merged 10 commits into from
Jun 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions examples/stimuli/advanced_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)

Expand All @@ -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:
Expand All @@ -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()
Expand Down
11 changes: 6 additions & 5 deletions expyfun/_experiment_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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]
Expand Down
7 changes: 6 additions & 1 deletion expyfun/_eyelink_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions expyfun/tests/test_experiment_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'):
Expand Down
29 changes: 20 additions & 9 deletions expyfun/visual/_visual.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
----------
Expand All @@ -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()

Expand Down Expand Up @@ -1112,17 +1112,23 @@ 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
The timestamp (on the parent ``ExperimentController`` timeline) at
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:
Expand All @@ -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:
Expand Down Expand Up @@ -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):
Expand Down