Exemple #1
0
    def continue_on(self):
        while True:
            if not P.development_mode:
                if key_pressed(key=sdl2.SDLK_KP_5):
                    break

            else:
                if key_pressed(key=sdl2.SDLK_k):
                    break
Exemple #2
0
 def jc_wait_time(self):
     if self.before_target:
         if lsl(self.el.gaze(), P.screen_c) > self.fixation_boundary:
             self.log_and_recycle_trial('eye')
         q = pump(True)
         if key_pressed(queue=q):
             if key_pressed(SDLK_SPACE, queue=q):
                 self.log_and_recycle_trial('early')
             else:
                 self.log_and_recycle_trial('key')
 def wait_time(self):
     # Appropriated verbatim from original code written by John Christie
     if self.before_target:
         gaze = self.el.gaze()
         if not self.bi.within_boundary(label='drift_correct', p=gaze):
             self.log_and_recycle_trial('eye')
         q = pump(True)
         if key_pressed(queue=q):
             if key_pressed(SDLK_SPACE, queue=q):
                 self.log_and_recycle_trial('early')
             else:
                 self.log_and_recycle_trial('key')
Exemple #4
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)
    def trial(self):

        if P.development_mode:
            print(self.image_name, self.mask_type)

        trial_countdown = CountDown(900) # 15 minutes
        while trial_countdown.remaining() > 0:
            q = pump(True)
            if key_pressed(sdl2.SDLK_DELETE, queue=q):
                # press 'Del' to skip trial
                break
            elif key_pressed(sdl2.SDLK_ESCAPE, queue=q):
                # Press 'escape' to pause and calibrate
                trial_countdown.pause()
                self.el.calibrate()
                self.el.drift_correct()
                self.el.start(P.trial_number)
                trial_countdown.resume()
                continue
            
            if trial_countdown.elapsed() >= self.first_warning_onset and not self.first_warning_played:
                self.warning_signal.play()
                self.first_warning_played = True
            if trial_countdown.elapsed() >= self.second_warning_onset and not self.second_warning_played:
                self.warning_signal.play()
                self.second_warning_played = True

            pos = self.el.gaze()
            fill()
            if int(pos[0]) != -32768: # if gaze not lost
                self.gaze_offscreen = time.time()
            if (pos[0] < 0) or (pos[0] > P.screen_x) or (pos[1] < 0) or (pos[1] > P.screen_y):
                pass
            elif (time.time() - self.gaze_offscreen) < self.gaze_timeout:
                blit(self.arrangement, 5, P.screen_c)
                if self.mask is not None and trial_countdown.elapsed() < self.mask_off_time:
                    blit(self.mask, 5, pos)
            flip()

        return {
            "trial_num":   P.trial_number,
            "block_num":   P.block_number,
            "arrangement": self.image_name,
            "mask_type":   self.mask_type
        }
Exemple #6
0
    def trial_clean_up(self):

        # Provide break 1/2 through experimental block
        if P.trial_number == P.trials_per_block / 2:
            txt = "You're 1/2 through, take a break if you like\nand press '5' when you're ready to continue"
            msg = message(txt, blit_txt=False)

            fill()
            blit(msg, location=P.screen_c, registration=5)
            flip()

            while True:
                if key_pressed(key=sdl2.SDLK_KP_5):
                    break
Exemple #7
0
    def __validate(self):
        instruction = (
            "Okay, threshold set! "
            "To ensure its validity, please provide one (and only one) more response."
        )
        fill()
        message(instruction, location=P.screen_c, registration=5)
        flip()
        self.stream.start()
        validate_counter = CountDown(5)
        while validate_counter.counting():
            ui_request()
            if self.stream.sample().peak >= self.threshold:
                validate_counter.finish()
                self.threshold_valid = True
        self.stream.stop()

        if self.threshold_valid:
            validation_msg = "Great, validation was successful! Press any key to continue."
        else:
            validation_msg = (
                "Validation wasn't successful. "
                "Type C to re-calibrate or V to try validation again.")
        fill()
        message(validation_msg, location=P.screen_c, registration=5)
        flip()
        selection_made = False
        while not selection_made:
            q = pump(True)
            if self.threshold_valid:
                if key_pressed(queue=q):
                    return
            else:
                if key_pressed(SDLK_c, queue=q):
                    self.calibrate()
                elif key_pressed(SDLK_v, queue=q):
                    self.__validate()
 def clean_up(self):
     # Give the RA the choice of logging or discarding combination of
     # factors used on last trial
     done_1 = message("Experiment session complete.", 'q_and_a', blit_txt=False)
     done_2 = message("Log trial factor set? (Y/N)", 'q_and_a', blit_txt=False)
     response_made = None
     
     while not response_made:
         fill()
         blit(done_1, 5, (P.screen_c[0], P.screen_c[1] - 40))
         blit(done_2, 5, (P.screen_c[0], P.screen_c[1] + 40))
         flip()
         q = pump(True)
         if key_pressed(sdl2.SDLK_y, queue=q):
             response_made = "Y"
             break
         elif key_pressed(sdl2.SDLK_n, queue=q):
             response_made = "N"
             break
                     
     if response_made == "Y":
         with open(self.completed_csv,"a") as f:
             writer = csv.writer(f)
             writer.writerow(sum(self.trial_factors, ()))
Exemple #9
0
    def present_feedback(self, prime_correct, prime_rt, probe_correct,
                         probe_rt):

        prime_fb = int(prime_rt) if prime_correct else 'WRONG'
        probe_fb = int(probe_rt) if probe_correct else 'WRONG'

        fb_txt = "{0}\n{1}".format(prime_fb, probe_fb)

        fb = message(fb_txt, align='center', blit_txt=False)

        fill()
        blit(fb, location=P.screen_c, registration=5)
        flip()

        while True:
            if key_pressed(key=sdl2.SDLK_SPACE):
                break
Exemple #10
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()
 def warm_up(self):
     warmup_timer = CountDown(600, start=True)
     self.first_signal_played = False
     self.second_signal_played = False
     self.third_signal_played = False
     self.fourth_signal_played = False
     while warmup_timer.counting():
         if key_pressed(sdl2.SDLK_DELETE):
             break
         
         t = warmup_timer.elapsed()
         if t < 60:
             tool = 'pencil'
         elif 60 <= t < 120:
             if not self.first_signal_played:
                 self.warning_signal.play()
                 self.first_signal_played = True
             tool = 'charcoal'
         elif 120 <= t < 180:
             if not self.second_signal_played:
                 self.warning_signal.play()
                 self.second_signal_played = True
             tool = 'smudger'
         elif 180 <= t < 240:
             if not self.third_signal_played:
                 self.warning_signal.play()
                 self.third_signal_played = True
             tool = 'eraser'
         else:
             if not self.fourth_signal_played:
                 self.warning_signal.play()
                 self.fourth_signal_played = True
             tool = 'any'
             
         fill()
         blit(self.images['warmup.png'], 5, P.screen_c)
         blit(self.warmup_txt[tool], 1, (30, P.screen_y-30))
         flip()
Exemple #12
0
    def block(self):

        halfway_block = (P.blocks_per_experiment / 2) + 1
        if P.run_practice_blocks and P.session_number == 1:
            halfway_block += 3

        if P.run_practice_blocks and P.session_number == 1 and P.block_number <= 3:
            txt = "This is a practice block ({0} of 3)\n\n".format(
                P.block_number)
            if P.block_number == 1:
                txt += (
                    "During this task, arrows will appear either above or below the '+' symbol.\n"
                    "Your job will be to indicate the direction of the middle arrow as quickly\n"
                    "and accurately as possible using the keyboard.\n\n"
                    "( c = left,  m = right )")
            elif P.block_number == 2:
                txt += (
                    "On some trials, the central arrow will be displaced upwards or downwards "
                    "by a large amount.\n"
                    "When this occurs, please press the space bar instead of the 'c' or 'm' keys."
                )
                self.trial_type = 'EV'
                self.ev_offset = 'below'
                demo_arrows = self.generate_arrows()
            else:
                txt += (
                    "On some trials, a large red countdown timer will appear instead of the arrows."
                    "\nWhen this occurs, please press the space bar as quickly as you can."
                )

            instructions = message(txt, align='center', blit_txt=False)
            continue_msg = message('Press any key to begin.',
                                   align='center',
                                   blit_txt=False)
            instruction_time = CountDown(3)
            while True:
                keydown = key_pressed()
                fill()
                blit(instructions, 8, (P.screen_c[0], int(P.screen_y * 0.1)))
                if P.block_number == 2:
                    blit(self.fixation, 5, P.screen_c)
                    for shape, loc in demo_arrows:
                        blit(shape, 5, loc)
                elif P.block_number == 3:
                    elapsed = min(
                        [int(instruction_time.elapsed() * 1000), 367])
                    demo_counter = message(str(elapsed).zfill(4),
                                           "PVT",
                                           blit_txt=False)
                    blit(demo_counter, 5, P.screen_c)
                if P.development_mode or instruction_time.counting() == False:
                    blit(continue_msg, 2,
                         (P.screen_c[0], int(P.screen_y * 0.9)))
                    if keydown == True:
                        break
                flip()

        elif P.run_practice_blocks and P.session_number == 1 and P.block_number == 4:
            self.block_msg(
                "Practice complete! Press any key to begin the task.")

        elif P.block_number == 1:
            self.block_msg("Press any key to begin the task.")

        elif P.block_number == halfway_block:
            self.block_msg(
                "Phew, you're halfway done! Press any key to continue.")
Exemple #13
0
    def trial(self):

        if P.development_mode:
            trial_info = (
                "\ntrial_type: '{0}', high_val_loc: '{1}', probe_loc: '{2}', "
                "cue_loc: '{3}', winning_bandit: '{4}'")
            print(
                trial_info.format(self.trial_type, self.high_value_location,
                                  self.probe_location, self.cue_location,
                                  self.winning_bandit))

        while self.evm.before('target_on', True) and not self.err:

            self.confirm_fixation()
            self.present_neutral_boxes()

            if self.evm.between('cue_on', 'cue_off'):
                if self.cue_location in [LEFT, DOUBLE]:
                    blit(self.thick_rect, 5, self.left_box_loc)
                if self.cue_location in [RIGHT, DOUBLE]:
                    blit(self.thick_rect, 5, self.right_box_loc)
            elif self.evm.between('cue_off', 'cueback_off'):
                blit(self.star_cueback, 5, P.screen_c)

            flip()

        self.targets_shown = True  # after bandits or probe shown, don't recycle trial on user error
        if self.trial_type in [BANDIT, BOTH] and not self.err:
            while self.evm.before('nogo_end') and not self.err:
                if key_pressed():
                    self.show_error_message('too_soon')
                    self.err = "early_response"
                    break
                self.confirm_fixation()
                self.bandit_callback(before_go=True)
                flip()

        #  PROBE RESPONSE PERIOD
        if self.trial_type in [PROBE, BOTH] and not self.err:
            self.probe_rc.collect()
            if not self.err:
                if len(self.probe_rc.keypress_listener.responses):
                    self.show_error_message('wrong_response')
                    self.err = 'keypress_on_probe'
                elif len(self.probe_rc.audio_listener.responses) == 0:
                    self.show_error_message('probe_timeout')
                    if self.probe_rc.audio_listener.stream_error:
                        self.err = 'microphone_error'
                    else:
                        self.err = 'probe_timeout'

        #  BANDIT RESPONSE PERIOD
        if self.trial_type in [BANDIT, BOTH] and not self.err:
            self.bandit_rc.collect()
            if self.trial_type == BANDIT and P.ignore_vocal_for_bandits == False:
                if len(self.bandit_rc.audio_listener.responses):
                    self.show_error_message('wrong_response')
                    self.err = 'vocal_on_bandit'

        # Retrieve collected response data before logging to database
        if self.err:
            bandit_choice, bandit_rt, reward = ['NA', 'NA', 'NA']
            probe_rt = 'NA'
        else:
            self.err = 'NA'
            # Retreive responses from RepsponseCollector(s) and record data
            if self.trial_type in [BANDIT, BOTH]:
                bandit_choice = self.bandit_rc.keypress_listener.response(
                    value=True, rt=False)
                bandit_rt = self.bandit_rc.keypress_listener.response(
                    value=False, rt=True)
                if bandit_rt == TIMEOUT:
                    self.show_error_message('bandit_timeout')
                    reward = 'NA'
                else:
                    # determine bandit payout (reward) and display feedback to participant
                    reward = self.feedback(bandit_choice)
            else:
                bandit_choice, bandit_rt, reward = ['NA', 'NA', 'NA']

            if self.trial_type in [PROBE, BOTH]:
                probe_rt = self.probe_rc.audio_listener.response(value=False,
                                                                 rt=True)
            else:
                probe_rt = 'NA'

        # Clear any remaining stimuli from screen before trial end
        clear()

        return {
            "block_num":
            P.block_number,
            "trial_num":
            P.trial_number,
            "trial_type":
            self.trial_type,
            "cue_loc":
            self.cue_location,
            "cotoa":
            self.cotoa,
            "high_value_col":
            self.high_value_color[:3] if self.trial_type != PROBE else "NA",
            "low_value_col":
            self.low_value_color[:3] if self.trial_type != PROBE else "NA",
            "high_value_loc":
            self.high_value_location if self.trial_type != PROBE else "NA",
            "winning_bandit":
            self.winning_bandit if self.trial_type != PROBE else "NA",
            "bandit_choice":
            bandit_choice,
            "bandit_rt":
            bandit_rt,
            "reward":
            reward,
            "probe_loc":
            self.probe_location if self.trial_type != BANDIT else "NA",
            "probe_rt":
            probe_rt,
            "err":
            self.err
        }
Exemple #14
0
    def trial(self):

        # Draw initial trial stimuli to screen

        fill()
        blit(self.accuracy_rect, 5, P.screen_c)
        blit(self.accuracy_mask, 5, P.screen_c)
        blit(self.letters[self.letter], 5, P.screen_c)
        flip()

        # Immediately start listening for reponses, removing letter after 500ms

        self.rc.collect()
        response = self.rc.keypress_listener.response()

        # Process collected response before writing to database, showing feedback if practicing

        if response.rt != klibs.TIMEOUT:
            resp, rt = response
            correct_resp = 'match' if self.is_target else 'nonmatch'
            accuracy = int(resp == correct_resp)
            if P.practicing:
                self.accuracy_rect.fill = MID_GREEN if accuracy == True else MID_RED
                self.accuracy_rect.render()
            while self.evm.before('trial_end'):
                ui_request()
                fill()
                blit(self.accuracy_rect, 5, P.screen_c)
                blit(self.accuracy_mask, 5, P.screen_c)
                if self.evm.before('mask_on'):
                    blit(self.letters[self.letter], 5, P.screen_c)
                else:
                    blit(self.mask, 5, P.screen_c)
                flip()
        else:
            resp, rt, accuracy = ['NA', 'NA', 'NA']

        # If probe trial, present MW probe and wait for response + keypress before ending trial

        if self.probe_trial:
            probe_resp, probe_rt = self.probe.collect()
            probe_rt = probe_rt * 1000  # convert seconds to ms
            resume_msg = message("Press the [n] key to continue.",
                                 'title',
                                 blit_txt=False)
            while True:
                if key_pressed('n'):
                    break
                fill()
                blit(resume_msg, 5, P.screen_c)
                flip()
            self.past_letters = []
        else:
            probe_resp, probe_rt = ('NA', 'NA')
            self.past_letters.append(self.letter)

        return {
            "block_num": P.block_number,
            "trial_num": P.trial_number,
            "practice": P.practicing,
            "probe_type": self.probe_condition,
            "first_nback": self.first_nback,
            "nback": self.nback,
            "target_trial": self.is_target,
            "resp": resp,
            "accuracy": accuracy,
            "rt": rt,
            "probe_resp": probe_resp,
            "probe_rt": probe_rt
        }
Exemple #15
0
    def block(self):

        # Initialize/reset list of previous letters presented

        self.past_letters = []

        # Determine nback difficulty for the block

        even_block = P.block_number % 2 == 0
        if self.first_nback == 1:
            self.nback = 2 if even_block else 1
        else:
            self.nback = 1 if even_block else 2

        # Determine positions of thought probes in trial sequence

        # Probes are pseudo-randomly distributed throughout blocks, with one probe in every set of
        # 30 trials. Probes cannot appear in the first 8 trials of a set, ensuring that probes are
        # at minimum 20 seconds apart.
        self.probe_trials = []
        noprobe_span = [False] * P.noprobe_span
        probe_span = [True] + [False] * P.probe_span
        while len(self.probe_trials) < P.trials_per_block:
            random.shuffle(probe_span)
            self.probe_trials += noprobe_span + probe_span

        # Generate block message

        header = "Block {0} of {1}".format(P.block_number,
                                           P.blocks_per_experiment)
        nback_txts = [' ', 'just before it', 'two before it']
        instructions = (
            "During this block, please press the [m] key when a letter matches\nthe letter "
            "{0}, and the [n] key when it does not.".format(
                nback_txts[self.nback]))
        if P.practicing:
            header = "This is a practice block. ({0})".format(header)
            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 [n] key to start.",
                            'normal',
                            blit_txt=False)

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

        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)))
            self.draw_nback_illustration(P.screen_c[1],
                                         target=5 if self.nback == 1 else 4)
            flip()

        while True:
            if key_pressed('n'):
                break
            fill()
            blit(msg, 8, (P.screen_c[0], int(P.screen_y * 0.15)))
            self.draw_nback_illustration(P.screen_c[1],
                                         target=5 if self.nback == 1 else 4)
            blit(start_msg, 5, (P.screen_c[0], int(P.screen_y * 0.75)))
            flip()
Exemple #16
0
    def trial(self):

        fill()
        blit(self.digits[self.number][self.num_size], 5, P.screen_c)
        flip()

        self.rc.collect()
        response = self.rc.keypress_listener.response()

        if response.rt == klibs.TIMEOUT:
            resp, rt = ['nogo', 'NA']
        else:
            resp, rt = response
        correct_resp = 'nogo' if self.number == P.target else 'go'
        accuracy = resp == correct_resp

        while self.evm.before('trial_end'):
            ui_request()
            fill()
            blit(self.mask_x, 5, P.screen_c)
            blit(self.mask_ring, 5, P.screen_c)
            flip()

        if P.practicing:
            if accuracy == False:
                feedback = "Incorrect! "
                if correct_resp == 'nogo':
                    feedback += "Please withhold responses to the digit {0}.".format(
                        P.target)
                else:
                    feedback += "Please respond quickly to digits other than {0}.".format(
                        P.target)
            else:
                feedback = "Correct response!"
            feedback_msg = message(feedback, 'normal', blit_txt=False)
            feedback_timer = CountDown(1.5)
            while feedback_timer.counting():
                ui_request()
                fill()
                blit(feedback_msg, 5, P.screen_c)
                flip()

        # If probe trial, present MW probe and wait for response + keypress before ending trial

        if self.probe_trial:
            probe_resp, probe_rt = self.probe.collect()
            eff_level, eff_rt = self.get_effort()
            probe_rt = probe_rt * 1000  # convert seconds to ms
            eff_rt = eff_rt * 1000  # convert seconds to ms
            eff_level = eff_level * 100  # scale range to 0% - 100%
            resume_msg = message("Press the [space] key to resume the task.",
                                 'title',
                                 blit_txt=False)
            while True:
                if key_pressed(' '):
                    break
                fill()
                blit(resume_msg, 5, P.screen_c)
                flip()
        else:
            probe_resp, probe_rt, eff_level, eff_rt = ('NA', 'NA', 'NA', 'NA')

        return {
            "practicing": P.practicing,
            "block_num": P.block_number,
            "trial_num": P.trial_number,
            "digit": self.number,
            "digit_size": self.num_size,
            "target_digit": P.target,
            "response": resp,
            "rt": rt,
            "accuracy": accuracy,
            "probe_resp": probe_resp,
            "probe_rt": probe_rt,
            "effort_level": eff_level,
            "effort_rt": eff_rt
        }