예제 #1
0
    def block(self):

        # Show block message at start of every block
        header = "Block {0} of {1}".format(P.block_number,
                                           P.blocks_per_experiment)
        if P.practicing:
            header = "This is a practice block. ({0})".format(header)
            practice_msg = "During this block you will be given feedback for your responses."
            msg = message(header + "\n" + practice_msg,
                          align="center",
                          blit_txt=False)
        else:
            msg = message(header, blit_txt=False)

        message_interval = CountDown(1)
        while message_interval.counting():
            ui_request()  # Allow quitting during loop
            fill()
            blit(msg, 8, (P.screen_c[0], P.screen_y * 0.4))
            flip()
        flush()

        start_msg = message("Press any key to start.", blit_txt=False)
        fill()
        blit(msg, 8, (P.screen_c[0], P.screen_y * 0.4))
        blit(start_msg, 5, [P.screen_c[0], P.screen_y * 0.6])
        flip()
        any_key()
예제 #2
0
파일: KeyFrames.py 프로젝트: LBRF/TraceLab
 def play(self):
     ui_request()
     for kf in self.key_frames:
         if kf.enabled:
             skip = kf.play()
             if skip:
                 break
예제 #3
0
    def feedback(self, response):
        correct_response = True if response == self.tilt_line_location else False

        # Every 5 trials of a particular payoff, ask anticipated earnings
        if self.potential_payoff == HIGH:
            self.high_value_trial_count += 1
            if self.high_value_trial_count in [5, 10, 15]:
                self.query_learning(HIGH)
        else:
            self.low_value_trial_count += 1
            if self.low_value_trial_count in [5, 10, 15]:
                self.query_learning(LOW)

        # Determine payout for trial
        if correct_response & (self.winning_trial == YES):
            points = self.payout()
            msg = message("You won {0} points!".format(points),
                          'myText',
                          blit_txt=False)
        else:
            points = self.penalty
            msg = message("You lost 5 points!", 'myText', blit_txt=False)
        # Keep tally of score
        self.total_score += points
        feedback = [points, msg]

        # Present score
        feedback_exposure = CountDown(self.feedback_exposure_period)
        fill()
        blit(feedback[1], location=P.screen_c, registration=5)
        flip()
        while feedback_exposure.counting():
            ui_request()

        return feedback[0]
예제 #4
0
 def run(self):
     if self.use_trial_clock:
         start = self.evm.trial_time
         if self.units == TK_S:
             start *= 0.001
     else:
         start = time()
         if self.units == TK_MS:
             start = int(start * 1000)
     for i in range(0, self.frame_count):
         if self.frames:
             for f in self.frames:
                 pass  # create a Frame class that knows how to blit itself after loading and rendering assets
         else:
             self.frame_draw_cb(*self.frame_draw_cb_args)
             if self.flip_after_cb:
                 flip()
         frame_running = True
         while frame_running:
             try:
                 self.frame_data_cb(self.frame_draw_cb_args)
             except TypeError:
                 pass
             if self.use_trial_clock:
                 elapsed = self.evm.trial_time
                 if self.units == TK_S:
                     elapsed *= 0.001
             else:
                 elapsed = time()
                 if self.units == TK_MS:
                     elapsed = int(start * 1000)
             frame_running = elapsed < i * self.frame_interval
             ui_request()
예제 #5
0
    def after(self, label, pump_events=False):
        """Checks if the current trial time is after a given event.

		.. warning:: Setting 'pump_events' to True will cause the input event queue to be cleared 
		  every time the method is called. Please use :func:`~.pump` manually in loops where you
		  will be processing user input.

		Args:
			label (str): The label of the event to check.
			pump_events (bool, optional): If True, a :func:`~.ui_request` is performed when this
				method is called. Defaults to False.

		Returns:
			True if the specified event has already occured within the trial, otherwise False.

		"""
        if type(label) is not str:
            raise ValueError(
                "Expected 'str' for argument label; got {0}.".format(
                    type(label)))
        if not self.registered(label):
            raise NameError(
                "Event '{0}' not registered with the EventManager.".format(
                    label))
        if pump_events:
            ui_request()

        return self.__event_issued(label)
예제 #6
0
파일: experiment.py 프로젝트: a-hurst/PVT
    def trial(self):

        # Clear screen and wait for target onset
        fill()
        flip()
        while self.evm.before('target_on'):
            ui_request()

        # Start timer and collect response
        self.rc.collect()
        response = self.rc.keypress_listener.response()

        # Stop timer and show for 1sec after response is made
        elapsed_msg = message(str(int(response.rt)).zfill(4),
                              style='PVT',
                              blit_txt=False)
        feedback_timer = CountDown(1)
        while feedback_timer.counting():
            fill()
            blit(elapsed_msg, 5, P.screen_c)
            flip()

        # Log trial data to database
        return {
            "block_num": P.block_number,
            "trial_num": P.trial_number,
            "isi": self.interstim_interval,
            "rt": response.rt
        }
예제 #7
0
    def start_trial_button(self):

        fill()
        blit(self.next_trial_box,
             5,
             self.next_trial_button_loc,
             flip_x=P.flip_x)
        blit(self.next_trial_msg,
             5,
             self.next_trial_button_loc,
             flip_x=P.flip_x)
        flip()

        if P.demo_mode or P.dm_always_show_cursor:
            show_mouse_cursor()

        flush()
        clicked = False
        while not clicked:
            event_queue = pump(True)
            for e in event_queue:
                if e.type == SDL_MOUSEBUTTONDOWN:
                    clicked = self.within_boundary("next trial button",
                                                   [e.button.x, e.button.y])
                elif e.type == SDL_KEYDOWN:
                    ui_request(e.key.keysym)

        if not (P.demo_mode or P.dm_always_show_cursor):
            hide_mouse_cursor()
예제 #8
0
    def imagery_trial(self):

        fill()
        blit(self.origin_inactive, 5, self.origin_pos, flip_x=P.flip_x)
        flip()

        start = self.evm.trial_time
        if P.demo_mode or P.dm_always_show_cursor:
            show_mouse_cursor()

        at_origin = False
        while not at_origin:
            x, y, button = mouse_pos(return_button_state=True)
            left_button_down = button == 1
            if self.within_boundary('origin', (x, y)) and left_button_down:
                at_origin = True
                self.rt = self.evm.trial_time - start
            ui_request()
        fill()
        blit(self.origin_active, 5, self.origin_pos, flip_x=P.flip_x)
        flip()

        while at_origin:
            x, y, button = mouse_pos(return_button_state=True)
            left_button_down = button == 1
            if not (self.within_boundary('origin',
                                         (x, y)) and left_button_down):
                at_origin = False
        self.mt = self.evm.trial_time - (self.rt + start)
        if P.demo_mode:
            hide_mouse_cursor()
예제 #9
0
    def _generate_figure(self, duration):

        failures = 0
        figure = None
        gen_start = time.time()
        while not figure:
            ui_request()
            try:
                figure = TraceLabFigure(animate_time=duration)
                figure.render()
                figure.prepare_animation()
            except RuntimeError as e:
                print(e)
                failures += 1
                if failures > 10:
                    print(
                        "\nUnable to generate a viable figure after 10 tries, quitting...\n"
                    )
                    self.quit()

        # Print warning if load time was particularly slow for a given figure
        if (time.time() - gen_start) > 0.5:
            cso("<red>Warning: figure generation took unexpectedly long. "
                "({0} seconds)</red>".format(round(time.time() - gen_start,
                                                   2)))

        return figure
예제 #10
0
    def get_effort(self):

        slider_loc = (P.screen_c[0], int(P.screen_y * 0.55))
        slider_cols = {'line': WHITE, 'slider': TRANSLUCENT_WHITE}
        scale = Slider(int(P.screen_x * 0.75),
                       ticks=5,
                       location=slider_loc,
                       fills=slider_cols)
        label_pad = scale.tick.surface_height

        show_mouse_cursor()
        onset = time.time()
        while True:
            sq = pump(True)
            ui_request(queue=sq)
            fill()
            blit(self.effort_q, 5, (P.screen_c[0], int(P.screen_y * 0.3)))
            blit(self.mineffort_msg, 8,
                 (scale.xmin, slider_loc[1] + label_pad))
            blit(self.maxeffort_msg, 8,
                 (scale.xmax, slider_loc[1] + label_pad))
            scale.draw()
            if scale.pos != None:
                self.submit.draw()
            flip()
            scale.listen(sq)
            if scale.pos != None:
                if self.submit.listen(sq) or key_pressed('Return', queue=sq):
                    rt = time.time() - onset
                    hide_mouse_cursor()
                    return (scale.pos, rt)
예제 #11
0
    def feedback(self, response):
        if self.winning_bandit == HIGH:
            winning_bandit_loc = self.high_value_location
        else:
            winning_bandit_loc = self.low_value_location

        if response == winning_bandit_loc:
            points = self.bandit_payout(value=self.winning_bandit)
            msg = message("You won {0} points!".format(points),
                          "score up",
                          blit_txt=False)
        else:
            points = self.penalty  # -5
            msg = message("You lost 5 points!", "score down", blit_txt=False)
        self.total_score += points
        feedback = [points, msg]

        feedback_exposure = CountDown(self.feedback_exposure_period)
        while feedback_exposure.counting():
            ui_request()
            fill()
            blit(feedback[1], location=P.screen_c, registration=5)
            flip()

        return feedback[0]
예제 #12
0
    def present_feedback(self):
        msg = "Incorrect!"

        self.blit_msg(msg, 'left')

        feedback_cd = CountDown(0.5)
        while feedback_cd.counting():
            ui_request()
예제 #13
0
	def trial(self):					
		# Wait 1s before presenting array
		while self.evm.before("present_fixation", True):
			ui_request()

		self.present_fixation()

		while self.evm.before("search_onset", True):
			ui_request()
		

		if self.search_type == SPACE:
			self.present_array()
			self.spatial_rc.collect()


			if len(self.spatial_rc.cursor_listener.responses):
				spatial_located, spatial_rt = self.spatial_rc.cursor_listener.response()
			else:
				spatial_located = 'miss'
				spatial_rt = 'NA'
		else:
			try:
				# the display callback "present_stream()" pops an element each pass; when all targets have been shown this bad boy throws an error
				self.temporal_rc.collect()
			except IndexError:
				self.temporal_responses = self.temporal_rc.mousebutton_listener.responses

		trial_data = {
			"block_num": P.block_number,
			"trial_num": P.trial_number,
			"search_type": "Spatial",
			"cell_count": self.cell_count,
			"target_distractor": self.target_distractor,
			"distractor_distractor": self.distractor_distractor,
		}
		if self.search_type == TIME:
			for tpt in self.temporal_presentation_times:
				onset_key = 't{0}_onset'.format(self.temporal_presentation_times.index(tpt)+1)
				onset_val = tpt[0]
				dist_count_key = 't{0}_distractor_count'.format(self.temporal_presentation_times.index(tpt)+1)
				dist_count_val = tpt[1]
				trial_data[onset_key] = onset_val
				trial_data[dist_count_key] = dist_count_val
		else:
			for i in range(0,15):
				onset_key = 't{0}_onset'.format(i+1)
				onset_val = 'NA'
				dist_count_key = 't{0}_distractor_count'.format(i+1)
				dist_count_val = 'NA'
				trial_data[onset_key] = onset_val
				trial_data[dist_count_key] = dist_count_val
		return trial_data
		clear()
예제 #14
0
파일: KeyFrames.py 프로젝트: LBRF/TraceLab
 def key_pressed(self, keysym, queue=None):
     pressed = False
     if not queue:
         queue = pump(True)
     for e in queue:
         if e.type == SDL_KEYDOWN:
             ui_request(e.key.keysym)
             if e.key.keysym.sym == keysym:
                 pressed = True
                 break
     return pressed
    def render_texture(self, texture_figure, orientation=None):
        grid_size = (deg_to_px(self.stim_size) + self.stim_pad) * 2
        stim_offset = self.stim_pad // 2
        dc = Image.new('RGB', (grid_size, grid_size), NEUTRAL_COLOR[:3])
        stroke_width = 2  #px
        grid_cell_size = deg_to_px(self.bg_element_size + self.bg_element_pad)
        grid_cell_count = grid_size // grid_cell_size
        stim_offset += (grid_size % grid_cell_size) // 2  # split grid_size %% cells over pad

        # Visual Representation of the Texture Rendering Logic
        # <-------G-------->
        #  _______________   ^
        # |       O       |  |    O = element_offset, ie. 1/2 bg_element_padding
        # |     _____     |  |    E = element (ie. circle, square, D, etc.)
        # |    |     |    |  |    G = one grid length
        # | O  |  E  |  O |  G
        # |    |_____|    |  |
        # |               |  |
        # |_______O_______|  |
        #                    v

        element_offset = self.bg_element_pad // 2  # so as to apply padding equally on all sides of bg elements
        for col in range(0, grid_cell_count):
            for row in range(0, grid_cell_count):
                ui_request()
                top_out = int(row * grid_cell_size + element_offset + stim_offset)
                top_in = top_out + stroke_width  # ie. top_inner
                left_out = int(col * grid_cell_size + element_offset + stim_offset)
                left_in = left_out+ stroke_width
                bottom_out = int(top_out + deg_to_px(self.bg_element_size))
                bottom_in = bottom_out - stroke_width
                right_out = int(left_out + deg_to_px(self.bg_element_size))
                right_in = right_out - stroke_width

                if texture_figure == CIRCLE:
                    ImageDraw.Draw(dc, 'RGB').ellipse((left_out, top_out, right_out, bottom_out), WHITE[:3])
                    ImageDraw.Draw(dc, 'RGB').ellipse((left_in, top_in, right_in, bottom_in), NEUTRAL_COLOR[:3])

                elif texture_figure == SQUARE:
                    ImageDraw.Draw(dc, 'RGB').rectangle((left_out, top_out, right_out, bottom_out), WHITE[:3])
                    ImageDraw.Draw(dc, 'RGB').rectangle((left_in, top_in, right_in, bottom_in), NEUTRAL_COLOR[:3])

                elif texture_figure is False:
                    half_el_width = int(0.5 * deg_to_px(self.bg_element_size))
                    rect_right = right_out - half_el_width
                    ImageDraw.Draw(dc, 'RGB', ).ellipse((left_out, top_out, right_out, bottom_out), WHITE[:3])
                    ImageDraw.Draw(dc, 'RGB', ).ellipse((left_in, top_in, right_in, bottom_in), NEUTRAL_COLOR[:3])
                    ImageDraw.Draw(dc, 'RGB', ).rectangle((left_out, top_out, rect_right, bottom_out), WHITE[:3])
                    ImageDraw.Draw(dc, 'RGB', ).rectangle((left_in, top_in, rect_right, bottom_in), NEUTRAL_COLOR[:3])

        dc = dc.resize((grid_size // 2, grid_size // 2), Image.ANTIALIAS)
        dc = dc.rotate(orientation)

        return dc
예제 #16
0
    def present_feedback(self):
        fill()
        message("Incorrect!",
                location=P.screen_c,
                registration=5,
                blit_txt=True)
        flip()

        feedback_period_cd = CountDown(0.5)  # seconds
        while feedback_period_cd.counting():
            ui_request()
예제 #17
0
    def _collect(self):

        q = pump(True)
        ui_request(queue=q)
        for e in q:
            if e.type == sdl2.SDL_MOUSEBUTTONDOWN:
                coords = (e.button.x, e.button.y)
                response = self.which_boundary(coords)
                if response != None:
                    return response
        return None
예제 #18
0
    def block(self):

        # Get response type and feedback type for block
        self.response_type = self.block_factors[P.block_number -
                                                1]['response_type']
        self.feedback_type = self.block_factors[P.block_number -
                                                1]['feedback_type']

        # If on first block of session, or response type is different from response type of
        # previous block, do tutorial animation and practice
        if self.response_type != self.prev_response_type:

            # Load instructions for new response type
            new_instructions = self.instruction_files[self.response_type]
            instructions_file = os.path.join(P.resources_dir, "Text",
                                             new_instructions['text'])
            inst_txt = io.open(instructions_file, encoding='utf-8').read()
            self.instructions = message(inst_txt,
                                        "instructions",
                                        align="center",
                                        blit_txt=False)

            if P.enable_practice:
                # Load tutorial animation for current condition, play it, and enter practice
                self.practice_kf = FrameSet(new_instructions['frames'],
                                            "assets")
                if P.block_number == 1:
                    fill()
                    blit(self.practice_instructions, 5, P.screen_c)
                    flip()
                    any_key()
                else:
                    self.start_trial_button()
                self.practice()

            self.prev_response_type = self.response_type

        for i in range(1, 4):
            # we do this a few times to avoid block messages being skipped due to duplicate input
            # from the touch screen we use
            ui_request()
            fill()
            blit(self.instructions,
                 registration=5,
                 location=P.screen_c,
                 flip_x=P.flip_x)
            flip()
        any_key()

        # Indicates if on first trial of block, needed for reloading incomplete sessions
        self.first_trial = True
예제 #19
0
	def drift_correct(self, location=None, target=None, fill_color=None, draw_target=True):
		"""Checks the accuracy of the eye tracker's calibration by presenting a fixation
		stimulus and requiring the participant to press the space bar while looking directly at
		it. If there is a large difference between the gaze location at the time the key was
		pressed and the true location of the fixation, it indicates that there has been drift
		in the calibration.

		In TryLink mode, drift correct targets are still displayed the same as with a hardware
		eye tracker. Simulated drift corrects are performed by clicking the drift correct target
		with the mouse.

		Args:
			location (Tuple(int, int), optional): The (x,y) pixel coordinates where the drift
				correct target should be located. Defaults to the center of the screen.
			target: A :obj:`Drawbject` or other :func:`KLGraphics.blit`-able shape to use as
				the drift correct target. Defaults to a circular :func:`drift_correct_target`.
			fill_color: A :obj:`List` or :obj:`Tuple` containing an RGBA colour to use for the
				background for the drift correct screen. Defaults to the value of
				``P.default_fill_color``.
			draw_target (bool, optional): A flag indicating whether the function should draw
				the drift correct target itself (True), or whether it should leave it to the
				programmer to draw the target before :meth:`drift_correct` is called (False). 
				Defaults to True.

		"""
		show_mouse_cursor()

		target = drift_correct_target() if target is None else target
		draw_target = EL_TRUE if draw_target in [EL_TRUE, True] else EL_FALSE
		location = P.screen_c if location is None else location
		if not iterable(location):
			raise ValueError("'location' must be a pair of (x,y) pixel coordinates.")
		dc_boundary = CircleBoundary('drift_correct', location, P.screen_y // 30)
		
		while True:
			event_queue = pump(True)
			ui_request(queue=event_queue)
			if draw_target == EL_TRUE:
				fill(P.default_fill_color if not fill_color else fill_color)
				blit(target, 5, location)
				flip()
			else:
				SDL_Delay(2) # required for pump() to reliably return mousebuttondown events
			for e in event_queue:
				if e.type == SDL_MOUSEBUTTONDOWN and dc_boundary.within([e.button.x, e.button.y]):
					hide_mouse_cursor()
					if draw_target == EL_TRUE:
						fill(P.default_fill_color if not fill_color else fill_color)
						flip()
					return 0
예제 #20
0
    def get_peak_during(self, period, msg=None):
        """Determines the peak loudness value recorded over a given period. Displays a visual
		callback that shows the current input volume and the loudest peak encounteredduring the
		interval so far.
		
		Args:
			period (numeric): the number of seconds to record input for.
			msg (:obj:`~klibs.KLGraphics.KLNumpySurface.NumpySurface`, optional): a rendered message
				to display in the top-right corner of the screen during the sampling loop.

		Returns:
			int: the loudest peak of all samples recorded during the period.

		"""
        local_peak = 0
        last_sample = 0
        if msg:
            msg = message(msg, blit_txt=False)

        flush()
        self.stream.start()
        sample_period = CountDown(period + 0.05)
        while sample_period.counting():
            ui_request()
            sample = self.stream.sample().peak
            if sample_period.elapsed() < 0.05:
                # Sometimes 1st or 2nd peaks are extremely high for no reason, so ignore first 50ms
                continue
            if sample > local_peak:
                local_peak = sample
            sample_avg = (sample + last_sample) / 2
            peak_circle = peak(5, int(
                (local_peak / 32767.0) * P.screen_y * 0.8))
            sample_circle = peak(
                5, int((sample_avg / 32767.0) * P.screen_y * 0.8))
            last_sample = sample

            fill()
            blit(Ellipse(peak_circle, fill=[255, 145, 0]),
                 location=P.screen_c,
                 registration=5)
            blit(Ellipse(sample_circle, fill=[84, 60, 182]),
                 location=P.screen_c,
                 registration=5)
            if msg:
                blit(msg, location=[25, 25], registration=7)
            flip()
        self.stream.stop()
        return local_peak
예제 #21
0
    def generate_locations(self):
        self.n_back_index = self.saccade_count - (
            2 + self.n_back
        )  # 1 for index, 1 b/c  n_back counts from penultimate saccade
        failed_generations = 0

        # generate locations until there are enough for the trial
        while len(self.disc_locations) < self.saccade_count:
            ui_request()
            try:
                self.disc_locations.append(DiscLocation())
            except TrialException:
                failed_generations += 1
                if failed_generations > 10:
                    raise
예제 #22
0
    def block(self):
        
        # Determine probe bias for block and generate list of probe locs accordingly
        
        if P.block_number > 3:
            self.probe_bias = "left"
            nonbiased_loc = "right"
        else:
            self.probe_bias = "right"
            nonbiased_loc = "left"
        loc_list = [self.probe_bias]*4 + [nonbiased_loc]
        self.probe_locs = loc_list * int(P.trials_per_block/float(len(loc_list))+1)
        random.shuffle(self.probe_locs)
        
        # At the start of each block, display a start message (block progress if experimental block,
        # practice message if practice block). After 3000ms, keypress will start first trial.
        
        probe_msg = (
            "During this block, the colour target will appear more often on the "
            "{0} and less often on the {1}.".format(self.probe_bias, nonbiased_loc)
        )
        header = "Block {0} of {1}".format(P.block_number, P.blocks_per_experiment)
        if P.practicing:
            header = "This is a practice block. ({0})".format(header)
        if P.block_number > 1:
            msg = message(header+"\n"+probe_msg, align="center", blit_txt=False)
        else:
            msg = message(header, blit_txt=False)

        message_interval = CountDown(1)
        while message_interval.counting():
            ui_request() # Allow quitting during loop
            fill()
            blit(msg, 8, (P.screen_c[0], P.screen_y*0.4))
            flip()
        flush()
        
        fill()
        blit(msg, 8, (P.screen_c[0], P.screen_y*0.4))
        message("Press any key to start.", registration=5, location=[P.screen_c[0], P.screen_y*0.6])
        flip()
        any_key()

        # When running participants, send halfway point and last-block notifications to researcher via Slack

        if not P.development_mode:
            if P.block_number == 3: # If participant is halfway done
                slack_message("Halfway done ({0}/{1})".format(P.block_number, P.blocks_per_experiment))
예제 #23
0
    def present_stream(self):
        # Each stream item presented for a pre-specified duration
        cd = CountDown(self.item_duration)
        sw = Stopwatch()
        for item in self.rsvp_stream:
            cd.reset()
            sw.reset()
            fill()
            blit(item, registration=5, location=P.screen_c)
            flip()

            #print(cd.elapsed)
            while cd.counting():
                ui_request()
            print(sw.elapsed())
            sw.reset()
예제 #24
0
    def trial(self):
        while self.evm.before("present_fixation", True):
            ui_request()

        self.blit_img(self.fixation, 5, P.screen_c)

        while self.evm.before("search_onset", True):
            ui_request()

        if self.search_type == SPACE:
            self.rc.collect()

        else:
            try:
                self.target_onset = 'NA'
                self.target_sw = Stopwatch()
                self.rc.collect()
            except IndexError:

                pass

        if len(self.rc.keypress_listener.responses):
            response, rt = self.rc.keypress_listener.response()
            if response != self.present_absent:
                self.present_feedback()

        else:
            response, rt = 'None', 'NA'

        clear()

        return {
            "practicing": str(P.practicing),
            "block_num": P.block_number,
            "trial_num": P.trial_number,
            "search_type": self.search_type,
            "stimulus_type": "LINE" if P.condition == 'line' else "COLOUR",
            "present_absent": self.present_absent,
            "set_size": self.set_size if self.search_type == SPACE else 'NA',
            "target_distractor": self.target_distractor,
            "distractor_distractor": self.distractor_distractor,
            "target_onset":
            self.target_onset if self.search_type == TIME else 'NA',
            "response": response,
            "rt": rt,
            "error": str(response != self.present_absent)
        }
예제 #25
0
파일: ButtonBar.py 프로젝트: LBRF/TraceLab
 def collect_response(self):
     self.start = time.time()
     finished = False
     selection = None
     last_selected = None
     flush()
     mt_start = None
     while not finished:
         show_mouse_cursor()
         events = pump(True)
         for e in events:
             if e.type == sdl2.SDL_KEYDOWN:
                 ui_request(e.key.keysym)
             elif e.type == sdl2.SDL_MOUSEBUTTONDOWN:
                 selection = None
                 for b in self.buttons:
                     if self.within_boundary(b.button_text,
                                             [e.button.x, e.button.y]):
                         self.toggle(b)
                         if not self.rt:
                             self.rt = time.time() - self.start
                             mt_start = time.time()
                         if b.active:
                             selection = b
                             last_selected = b
                             if callable(b.callback):
                                 if self.finish_b is None:
                                     return b.callback
                                 else:
                                     b.callback()
                     try:
                         if self.finish_b.active and self.within_boundary(
                                 "Done", [e.button.x, e.button.y]):
                             self.response = int(last_selected.button_text)
                             self.mt = time.time() - mt_start
                             finished = True
                     except AttributeError:
                         pass
         try:
             self.finish_b.active = selection is not None
         except AttributeError:
             pass
         self.render()
     fill()
     flip()
     hide_mouse_cursor()
예제 #26
0
 def get_input_key(self):
     keys = []
     for event in pump(True):
         if event.type == sdl2.SDL_KEYDOWN:
             keysym = event.key.keysym
             if not self.el._quitting:
                 # don't process quit requests while already quitting
                 ui_request(keysym)
             try:
                 key = self.pylink_keycodes[keysym.sym]
             except KeyError:
                 key = keysym.sym
             # don't allow escape to control tracker unless calibrating
             if key == pylink.ESC_KEY and not self.el.in_setup:
                 key = pylink.JUNK_KEY
             keys.append(pylink.KeyInput(key, keysym.mod))
     return keys
예제 #27
0
def smart_sleep(interval, units=TK_MS):
    """Stops and waits for a given amount of time, ensuring that any 'quit' or 'calibrate' key
	commands issued during the wait interval are processed.

	Args:
		interval (float): The number of units of time to pause execution for.
		units (int, optional): The time unit of 'interval', must be one of `klibs.TK_S` (seconds)
			or `klibs.TK_MS` (milliseconds). Defaults to milliseconds.
			
	"""
    from klibs.KLUserInterface import ui_request
    from klibs.KLTime import precise_time
    if units == TK_MS:
        interval *= .001
    start = precise_time()
    while precise_time() - start < interval:
        ui_request()
예제 #28
0
 def click_to_continue(self):        
     util.show_mouse_cursor()
     wait_for_click = True
     while wait_for_click:
         fill()
         blit(self.next_trial_circle, 5, P.screen_c)
         flip()
         events = util.pump(True)
         ui_request(queue=events)
         for e in events:
             if e.type == sdl2.SDL_MOUSEBUTTONUP:
                 pos = (e.button.x, e.button.y)
                 if self.within_boundary("center", pos):
                     fill()
                     flip()
                     wait_for_click = False      
     util.hide_mouse_cursor()
예제 #29
0
    def block(self):

        # Generate font sizes to use for numbers during the block

        self.num_sizes = []
        while len(self.num_sizes) <= P.trials_per_block:
            self.num_sizes = self.num_sizes + self.sizes
        random.shuffle(self.num_sizes)
        self.num_sizes = self.num_sizes[0:P.trials_per_block]

        # Generate block message

        header = ""  #"Block {0} of {1}".format(P.block_number, P.blocks_per_experiment)
        instructions = (
            "Please press the space key quickly when a digit other than {0} \nappears on screen, "
            "and withhold your response when the digit is {0}.".format(
                P.target))
        if P.practicing:
            header = "This is a practice block."
            instructions = instructions + "\nYou will be given feedback on your accuracy."
        msg = message(header + "\n\n" + instructions,
                      'normal',
                      align="center",
                      blit_txt=False)
        start_msg = message("Press the [space] key to start.",
                            'normal',
                            blit_txt=False)

        # Show block message, and wait for input before staring block

        if P.block_number in [1, self.first_nonpractice]:
            message_interval = CountDown(2)
            while message_interval.counting():
                ui_request()  # Allow quitting during loop
                fill()
                blit(msg, 8, (P.screen_c[0], int(P.screen_y * 0.15)))
                flip()

            while True:
                if key_pressed(' '):
                    break
                fill()
                blit(msg, 8, (P.screen_c[0], int(P.screen_y * 0.15)))
                blit(start_msg, 5, (P.screen_c[0], int(P.screen_y * 0.75)))
                flip()
예제 #30
0
    def collect(self):

        show_mouse_cursor()
        onset = time.time()

        while self.scale.response == None:
            q = pump(True)
            ui_request(queue=q)
            fill()
            blit(self.q, location=self.origin, registration=8)
            self.scale.response_listener(q)
            flip()

        response = self.scale.response
        rt = time.time() - onset
        hide_mouse_cursor()
        self.scale.response = None  # reset for next time
        return Response(response, rt)
    def trial(self):
        """
        trial_factors: 1 = mask_type, 2 = target_level, 3 = mask_size, 4 = target_shape]
        """
        if P.development_mode:
            print(self.mask_type, self.target_level, self.mask_size, self.target_shape)
        
        self.rc.collect()
        resp = self.rc.keypress_listener.response()
        
        if P.development_mode:
            print(resp)

        # handle timeouts
        if resp.rt == TIMEOUT:
            feedback = CountDown(1)
            msg = message("Too slow!", "alert", blit_txt=False)
            while feedback.counting():
                ui_request()
                fill()
                blit(msg, 5, P.screen_c)
                flip()
            clear()

        #  create readable data as fixation is currrently in (x,y) coordinates

        if self.fixation == self.fixation_top:
            initial_fixation = "TOP"
        elif self.fixation == self.fixation_central:
            initial_fixation = "CENTRAL"
        else:
            initial_fixation = "BOTTOM"

        return {"practicing": P.practicing,
                "response": resp.value,
                "rt": float(resp.rt),
                "mask_type": self.mask_type,
                "mask_size": self.mask_size,
                "local": self.target_shape if self.target_level == LOCAL else "D",
                "global": self.target_shape if self.target_level == GLOBAL else "D",
                "d_orientation": self.orientation,
                "trial_num": P.trial_number,
                "block_num": P.block_number,
                "initial_fixation": initial_fixation}