def __init__(self, prepare, wait, view, flag, wait_style_fixed=False, print_frames=False, suspendable=True, pre_stimulus=None, frame_transition=False, vsync=True): self._prepare_func = prepare self._wait_times = itertools.cycle(wait) self._view = view self._flag = flag self._wait_style_fixed = wait_style_fixed self._print_frames = print_frames self._suspendable = suspendable self._pre_stimulus = pre_stimulus self._frame_transition = frame_transition self._vsync = vsync self._logger = logging.getLogger('StimulusPainter') self._frame_counter = FrameCounter(self._flag) self._suspended_time = timedelta() self._wait = self._frame_wait if frame_transition else self._time_wait self._online_times = []
class StimulusPainter(object): """ Painter for a series of stimuli. """ def __init__(self, prepare, wait, view, flag, wait_style_fixed=False, print_frames=False, suspendable=True, pre_stimulus=None, frame_transition=False, vsync=True): self._prepare_func = prepare self._wait_times = itertools.cycle(wait) self._view = view self._flag = flag self._wait_style_fixed = wait_style_fixed self._print_frames = print_frames self._suspendable = suspendable self._pre_stimulus = pre_stimulus self._frame_transition = frame_transition self._vsync = vsync self._logger = logging.getLogger('StimulusPainter') self._frame_counter = FrameCounter(self._flag) self._suspended_time = timedelta() self._wait = self._frame_wait if frame_transition else self._time_wait self._online_times = [] def run(self): if self._print_frames or self._frame_transition: self._frame_counter.start() if self._prepare(): self._last_start = datetime.now() self._frame_counter.lock() self._present() while self._prepare(): self._wait() self._present() if self._flag: self._wait() if self._print_frames: self._logger.debug('Frames rendered during last sequence: %d' % self._frame_counter.frame) def _frame_wait(self): next_interval = self._next_duration while self._flag and self._frame_counter.last_interval < next_interval: self._frame_counter.sync() if self._print_frames: self._logger.debug('Frames after waiting: %d' % self._frame_counter.last_interval) def _time_wait(self): next_start = self._last_start + self._next_duration while next_start - datetime.now() > timedelta(): pass self._last_start = (next_start if self._wait_style_fixed else datetime.now()) if self._print_frames: self._logger.debug('Frames after waiting: %d' % self._frame_counter.last_interval) def _prepare(self): if self._flag: if self._suspendable and self._flag.suspended: suspend_start = datetime.now() self._flag.wait() self._suspended_time = datetime.now() - suspend_start return self._do_prepare() def _present(self): if self._print_frames: self._logger.debug('Frames before stimulus change: %d' % self._frame_counter.last_interval) if self._pre_stimulus is not None: self._pre_stimulus() self._frame_counter.lock() self._view.update() @property def _next_duration(self): try: nxt = self._online_times.pop(0) or self._wait_times.next() except StopIteration: raise Exception('No specified stimulus times available!') return nxt(self._frame_transition) + self._suspended @property def _suspended(self): t = self._suspended_time self._suspended_time = timedelta() return _frames(t.total_seconds()) if self._frame_transition else t