Пример #1
0
    def calc_flip_interval(self, nflips=55, nignore=5):
        diffs = 0.0
        last_time = 0.0
        count = 0.0
        for i in range(nflips):
            # perform the flip and record the flip interval
            cur_time = self.blocking_flip()
            if last_time > 0.0 and i >= nignore:
                diffs += cur_time['time'] - last_time['time']
                count += 1
            last_time = cur_time

            # add in sleep of something definitely less than the refresh rate
            clock.usleep(5000)  # 5ms for 200Hz
        
        # take the mean and return
        self.flip_interval = diffs / count
        return self.flip_interval
Пример #2
0
    def _idle_callback(self, event_loop):
        # record the time range
        self._new_time = clock.now()
        time_err = (self._new_time - self._last_time) / 2.0
        self.event_time = event_time(self._last_time + time_err, time_err)

        # call any of our scheduled events that are ready
        clock.tick()

        # see if we're ready for video
        ready_for_video = ((self._new_time - self.last_flip["time"]) >=
                           (self.flip_interval - FLIP_TIME_MARGIN))

        # see if the kivy clock needs a tick
        # throttled by flip interval
        ready_for_kivy_tick = ready_for_video and (self._new_time -
                                                   self._last_kivy_tick >=
                                                   self.flip_interval)

        # prepare for every video to be drawn on the next flip
        need_draw = False
        for video in self.video_queue:
            if (not video.drawn and
                ((self.pending_flip_time is None and
                  self._new_time >= (video.flip_time -
                                     (self.flip_interval / 2.0))) or
                 video.flip_time == self.pending_flip_time)):
                # prepare that video change
                video.update_cb()
                need_draw = True
                video.drawn = True

                # save the pending time so all other changes
                # for that time will also run
                self.pending_flip_time = video.flip_time
            else:
                # either none are ready or the remaining are
                # for a subsequent flip
                break

        # do a kivy tick if we're going to be drawing or enough time
        # has passed (see above)
        do_kivy_tick = ready_for_kivy_tick or need_draw
        if do_kivy_tick:
            # tick the kivy clock
            _kivy_clock.tick()
            self._last_kivy_tick = self._new_time

        # dispatch input events
        event_loop.dispatch_input()

        # process the builder and check for kivy draws
        if do_kivy_tick:
            Builder.sync()
            _kivy_clock.tick_draw()
            Builder.sync()
            kivy_needs_draw = EventLoop.window.canvas.needs_redraw or need_draw
            # print (_kivy_clock.get_fps(),
            # _kivy_clock.get_rfps(), self._new_time)
        else:
            kivy_needs_draw = False

        # dispatch draw if necessary
        if kivy_needs_draw:
            EventLoop.window.dispatch('on_draw')

        # handle video and flips
        if ready_for_video:
            # we need flip if kivy needs one
            need_flip = kivy_needs_draw and self.pending_flip_time is None
            flip_time_callbacks = []
            for video in self.video_queue:
                if video.drawn and video.flip_time == self.pending_flip_time:
                    # a smile video change is ready, so we need flip
                    need_flip = True

                    # append the flip time callback
                    if video.flip_time_cb is not None:
                        flip_time_callbacks.append(video.flip_time_cb)

                    # mark that video as flipped (it's gonna be)
                    video.flipped = True
                else:
                    # no more of the videos could match, so break
                    break

            # remove any video change that's gonna be flipped
            while len(self.video_queue) and self.video_queue[0].flipped:
                del self.video_queue[0]

            # do flip if necessary
            if need_flip:
                # test if blocking or non-blocking flip
                # do a blocking if:
                # 1) The pending flip is outside a single flip interval
                # AND
                #   2) Forcing a blocking flip_interval
                #   OR
                #   3) We have a specific flip callback request and we
                #      are not forcing  a non-blocking flip
                if (self.pending_flip_time >
                    (self.last_flip['time'] +
                     self.flip_interval +
                     FLIP_TIME_MARGIN)) and \
                   (self.force_blocking_flip or
                    (len(flip_time_callbacks) and
                     not self.force_nonblocking_flip)):
                    # print "BLOCKING FLIP!"
                    self.blocking_flip()
                    # for cb in flip_time_callbacks:
                    #     cb(self.last_flip)
                else:
                    # non-blicking flip
                    # print "FLIP!"
                    EventLoop.window.dispatch('on_flip')
                    self.last_flip = event_time(clock.now(), 0.0)

                # still may need to update flip_time_callbacks
                # even though they will be wrong
                for cb in flip_time_callbacks:
                    cb(self.last_flip)

                # tell refs that last_flip updated
                self.last_flip_ref.dep_changed()

                # no longer pending flip
                self.pending_flip_time = None

        # save the time
        self._last_time = self._new_time

        # exit if experiment done
        if not self.exp._root_executor._active:
            if self.exp._root_executor._enter_time:
                # stop if we're not active, but we have an enter time
                self.stop()

        # give time to other threads
        clock.usleep(250)
Пример #3
0
    def _idle_callback(self, event_loop):
        # record the time range
        self._new_time = clock.now()
        time_err = (self._new_time - self._last_time) / 2.0
        self.event_time = event_time(self._last_time + time_err, time_err)

        clock.tick()

        ready_for_video = (self._new_time - self.last_flip["time"] >=
                           self.flip_interval)
        ready_for_kivy_tick = ready_for_video and (self._new_time -
                                                   self._last_kivy_tick >=
                                                   self.flip_interval)

        need_draw = False
        for video in self.video_queue:
            if (not video.drawn and
                ((self.pending_flip_time is None and
                  self._new_time >= video.flip_time -
                  self.flip_interval / 2.0) or
                 video.flip_time == self.pending_flip_time)):
                video.update_cb()
                need_draw = True
                video.drawn = True
                self.pending_flip_time = video.flip_time
            else:
                break
        do_kivy_tick = ready_for_kivy_tick or need_draw
        if do_kivy_tick:
            _kivy_clock.tick()
            self._last_kivy_tick = self._new_time
        event_loop.dispatch_input()
        if do_kivy_tick:
            Builder.sync()
            _kivy_clock.tick_draw()
            Builder.sync()
            kivy_needs_draw = EventLoop.window.canvas.needs_redraw or need_draw
            #print (_kivy_clock.get_fps(), _kivy_clock.get_rfps(), self._new_time)  #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        else:
            kivy_needs_draw = False
        if kivy_needs_draw:
            EventLoop.window.dispatch('on_draw')

        if ready_for_video:
            need_flip = kivy_needs_draw and self.pending_flip_time is None
            flip_time_callbacks = []
            for video in self.video_queue:
                if video.drawn and video.flip_time == self.pending_flip_time:
                    need_flip = True
                    if video.flip_time_cb is not None:
                        flip_time_callbacks.append(video.flip_time_cb)
                    video.flipped = True
                else:
                    break
            while len(self.video_queue) and self.video_queue[0].flipped:
                del self.video_queue[0]
            if need_flip:
                if len(flip_time_callbacks):
                    #print "BLOCKING FLIP!"  #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    self.blocking_flip()  #TODO: use sync events instead!
                    for cb in flip_time_callbacks:
                        cb(self.last_flip)
                else:
                    #print "FLIP!"  #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    EventLoop.window.dispatch('on_flip')
                    self.last_flip = event_time(clock.now(), 0.0)
                self.pending_flip_time = None

        # save the time
        self._last_time = self._new_time

        # exit if experiment done
        if not self.exp._root_state._active:
            self.stop()

        # give time to other threads
        clock.usleep(250)
Пример #4
0
    def _idle_callback(self, event_loop):
        # record the time range
        self._new_time = clock.now()

        # call any of our scheduled events that are ready
        clock.tick()

        # dispatch input events
        time_err = (clock.now() - self._post_dispatch_time) / 2.0
        self.dispatch_input_event_time = event_time(self._post_dispatch_time +
                                                    time_err, time_err)
        event_loop.dispatch_input()
        self._post_dispatch_time = clock.now()

        # processing video and drawing can only happen if we have
        # not already drawn
        if not self._did_draw:
            # prepare for every video to be drawn on the next flip
            for video in self.video_queue:
                # the desired video time must be after the previous flip
                # is done, so making sure the next_flip_time is after
                # ensures this is the case
                if (video.flip_time - self._next_flip_time) < 0.0:

                    if (not video.drawn and
                        ((self.pending_flip_time is None and
                          self._new_time >= (video.flip_time -
                                             (self.flip_interval / 2.0))) or
                         video.flip_time == self.pending_flip_time)):
                        # prepare that video change
                        video.update_cb()

                        # it will be drawn
                        video.drawn = True

                        # save the pending time so all other changes
                        # for that time will also run
                        self.pending_flip_time = video.flip_time
                    else:
                        # either none are ready or the remaining are
                        # for a subsequent flip
                        break
                else:
                    break

            # do kivy ticks and draw when we're ready
            # happens at half the flip interval since last flip
            if clock.now() >= self._next_draw_time:
                # tick the kivy clock
                _kivy_clock.tick()

                # sync Builder and call tick_draw to prepare to draw
                Builder.sync()
                _kivy_clock.tick_draw()
                Builder.sync()
                EventLoop.window.dispatch('on_draw')

                # process smile video callbacks for the upcoming flip
                self._flip_time_callbacks = []
                for video in self.video_queue:
                    if video.drawn and video.flip_time == self.pending_flip_time:
                        # append the flip time callback
                        if video.flip_time_cb is not None:
                            self._flip_time_callbacks.append(video.flip_time_cb)

                        # mark that video as flipped (it's gonna be)
                        video.flipped = True
                    else:
                        # no more of the videos could match, so break
                        break

                # remove any video change that's gonna be flipped
                while len(self.video_queue) and self.video_queue[0].flipped:
                    del self.video_queue[0]

                # we've drawn the one time we can this frame
                self._did_draw = True

        # do a flip when we're ready
        # must have completed draw (this will ensure we don't do double flips
        # inside the FLIP_TIME_MARGIN b/c did_draw will be reset to False upon
        # the flip
        if self._did_draw and \
           clock.now() >= self._next_flip_time-FLIP_TIME_MARGIN:
            # test if blocking or non-blocking flip
            # do a blocking if:
            # 1) Forcing a blocking flip_interval
            #   OR
            # 2) We have a specific flip callback request and we
            #      are not forcing a non-blocking flip
            if self.force_blocking_flip or \
               (len(self._flip_time_callbacks) and
                not self.force_nonblocking_flip):
                # do a blocking flip
                self.do_flip(block=True)
            else:
                # do a non-blocking flip
                self.do_flip(block=False)

            # still may need to update flip_time_callbacks
            # even though they may be wrong for non-blocking flips
            for cb in self._flip_time_callbacks:
                cb(self.last_flip)

            # tell refs that last_flip updated
            self.exp._screen._set_last_flip(self.last_flip)

            # reset for next flip
            self.pending_flip_time = None

        # exit if experiment done
        if not self.exp._root_executor._active:
            if self.exp._root_executor._enter_time:
                # stop if we're not active, but we have an enter time
                self.stop()

        # give time to other threads
        clock.usleep(IDLE_USLEEP)

        # save the time
        self._last_time = clock.now()
        time_err = (self._last_time - self._new_time) / 2.0
        self.event_time = event_time(self._new_time + time_err, time_err)