Beispiel #1
0
    def present_spatial_array(self, spatial_array):
        fill()
        blit(self.fixation, registration=5, location=P.screen_c)

        if P.development_mode:
            c = kld.Annulus(deg_to_px(1.0),
                            deg_to_px(0.1),
                            fill=(255, 0, 0, 255))
            blit(c, registration=5, location=self.target_loc)
        for item in spatial_array:
            blit(item[0], registration=5, location=item[1])
        flip()
Beispiel #2
0
    def setup(self):

        box_size = deg_to_px(1.8)
        box_thick = deg_to_px(0.05)
        stim_size = deg_to_px(0.95)
        stim_thick = deg_to_px(0.1)
        fix_size = deg_to_px(1)
        fix_offset = deg_to_px(2.8)

        box_stroke = [box_thick, WHITE, STROKE_CENTER]

        self.txtm.add_style(label='greentext', color=GREEN)

        self.target = kld.Annulus(diameter=stim_size,
                                  thickness=stim_thick,
                                  fill=WHITE)
        self.distractor = kld.FixationCross(size=stim_size,
                                            thickness=stim_thick,
                                            fill=WHITE)

        # Set the rotation of placeholder boxes & fixation to match that of the display (diamond, square)
        rotate = 45 if P.condition == 'diamond' else 0
        self.placeholder = kld.Rectangle(width=box_size,
                                         stroke=box_stroke,
                                         rotation=rotate)
        self.fixation = kld.Asterisk(size=fix_size,
                                     thickness=stim_thick,
                                     fill=WHITE,
                                     rotation=rotate,
                                     spokes=8)

        # Which locations are labelled far or near is dependent on arrangement of display
        # 'near' locations refer to those that lie at the intersection of 'far' locations
        if P.condition == 'square':
            self.far_locs = {
                1: [
                    point_pos(P.screen_c,
                              amplitude=fix_offset,
                              angle=315,
                              clockwise=True), 'NorthEast'
                ],
                2: [
                    point_pos(P.screen_c,
                              amplitude=fix_offset,
                              angle=45,
                              clockwise=True), 'SouthEast'
                ],
                3: [
                    point_pos(P.screen_c,
                              amplitude=fix_offset,
                              angle=135,
                              clockwise=True), 'SouthWest'
                ],
                4: [
                    point_pos(P.screen_c,
                              amplitude=fix_offset,
                              angle=225,
                              clockwise=True), 'NorthWest'
                ]
            }

            self.near_locs = {
                5:
                [midpoint(self.far_locs[4][0], self.far_locs[1][0]), 'North'],
                6:
                [midpoint(self.far_locs[1][0], self.far_locs[2][0]), 'East'],
                7:
                [midpoint(self.far_locs[3][0], self.far_locs[2][0]), 'South'],
                8:
                [midpoint(self.far_locs[3][0], self.far_locs[4][0]), 'West']
            }

        else:  # if P.condition == 'diamond'
            self.far_locs = {
                1: [
                    point_pos(P.screen_c,
                              amplitude=fix_offset,
                              angle=270,
                              clockwise=True), 'North'
                ],
                2: [
                    point_pos(P.screen_c,
                              amplitude=fix_offset,
                              angle=0,
                              clockwise=True), 'East'
                ],
                3: [
                    point_pos(P.screen_c,
                              amplitude=fix_offset,
                              angle=90,
                              clockwise=True), 'South'
                ],
                4: [
                    point_pos(P.screen_c,
                              amplitude=fix_offset,
                              angle=180,
                              clockwise=True), 'West'
                ]
            }

            self.near_locs = {
                5: [
                    midpoint(self.far_locs[4][0], self.far_locs[1][0]),
                    'NorthWest'
                ],
                6: [
                    midpoint(self.far_locs[1][0], self.far_locs[2][0]),
                    'NorthEast'
                ],
                7: [
                    midpoint(self.far_locs[3][0], self.far_locs[2][0]),
                    'SouthEast'
                ],
                8: [
                    midpoint(self.far_locs[3][0], self.far_locs[4][0]),
                    'SouthWest'
                ]
            }

        if not P.development_mode:
            self.keymap = KeyMap('directional_response', [
                'North', 'NorthEast', 'East', 'SouthEast', 'South',
                'SouthWest', 'West', 'NorthWest'
            ], [
                'North', 'NorthEast', 'East', 'SouthEast', 'South',
                'SouthWest', 'West', 'NorthWest'
            ], [
                sdl2.SDLK_KP_8, sdl2.SDLK_KP_9, sdl2.SDLK_KP_6, sdl2.SDLK_KP_3,
                sdl2.SDLK_KP_2, sdl2.SDLK_KP_1, sdl2.SDLK_KP_4, sdl2.SDLK_KP_7
            ])

        else:  # Don't have a numpad myself, so I need an alternative when developing
            self.keymap = KeyMap('directional_response', [
                'North', 'NorthEast', 'East', 'SouthEast', 'South',
                'SouthWest', 'West', 'NorthWest'
            ], [
                'North', 'NorthEast', 'East', 'SouthEast', 'South',
                'SouthWest', 'West', 'NorthWest'
            ], [
                sdl2.SDLK_i, sdl2.SDLK_o, sdl2.SDLK_l, sdl2.SDLK_PERIOD,
                sdl2.SDLK_COMMA, sdl2.SDLK_m, sdl2.SDLK_j, sdl2.SDLK_u
            ])

        # Prime items always presented in far locations
        self.prime_locs = self.far_locs.copy()
        # Probe items can be far or near, determined conditionally
        self.probe_locs = dict(self.near_locs.items() + self.far_locs.items())

        # So, to get a practice block of 25, we first need to generate the full set of 2048
        # possible permutations, trim that down to the 288 legitimate permutations,
        # then trim that down to 25...
        self.insert_practice_block(1, 2048)

        # Because KLibs auto-generates trials for each product of ind_vars.py,
        # a lot of 'vestigial' trials are generated that we don't want, this sorts
        # through the trial list and removes those trials.
        for ind_b, block in enumerate(self.trial_factory.blocks):
            for trial in block:

                # targets & distractors cannot overlap within a given display
                if trial[1] == trial[2] or trial[3] == trial[4]:

                    self.trial_factory.blocks[ind_b].remove(trial)
                    block.i -= 1
                    block.length = len(block.trials)
                    continue
                # For 'near' trials, Ts & Ds cannot appear at 'far' locations
                if trial[0] == 'near':
                    if trial[3] < 5 or trial[4] < 5:

                        self.trial_factory.blocks[ind_b].remove(trial)
                        block.i -= 1
                        block.length = len(block.trials)

                # Conversely, cannot appear at 'near' locations on 'far' trials
                else:
                    if trial[3] > 4 or trial[4] > 4:

                        self.trial_factory.blocks[ind_b].remove(trial)
                        block.i -= 1
                        block.length = len(block.trials)

            # We only want 25 trials for practice, this trims the block
            # to the appropriate length
            if ind_b == 0:
                for trial in block:
                    self.trial_factory.blocks[ind_b].remove(trial)
                    block.i -= 1
                    block.length = len(block.trials)

                    if block.length == 25:
                        break

        # Set to True once instructions are provided
        self.instructed = False
Beispiel #3
0
    def setup(self):

        # Initialize stimulus sizes

        mask_size_x = deg_to_px(3.0)
        mask_size_ring = deg_to_px(4.0)
        mask_thick = deg_to_px(0.3)

        # Initialize text styles
        self.txtm.add_style('normal', '0.7deg')
        self.txtm.add_style('title', '1.0deg')

        self.mask_x = kld.Asterisk(mask_size_x,
                                   mask_thick,
                                   fill=P.default_color,
                                   spokes=8)
        self.mask_ring = kld.Annulus(mask_size_ring,
                                     mask_thick,
                                     fill=P.default_color)

        self.digits = {}
        digits = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        for digit in digits:
            self.digits[digit] = {}

        self.sizes = ['1.5deg', '2.0deg', '2.5deg', '3.0deg', '3.5deg']
        for size in self.sizes:
            self.txtm.add_style(size, size)

        for digit in digits:
            for size in self.sizes:
                self.digits[digit][size] = message(str(digit),
                                                   style=size,
                                                   blit_txt=False)

        # Initialize thought probes

        p_title = message(P.probe_question, "title", blit_txt=False)
        p_responses = P.probe_responses
        p_order = P.probe_order
        p_origin = (P.screen_c[0], P.screen_x // 10)
        self.probe = ThoughtProbe(p_responses, p_title, int(P.screen_x * 0.8),
                                  p_origin, p_order)

        # Initialize effort probes

        qeffort_text = "How much effort were you putting into staying on-task?"
        self.effort_q = message(qeffort_text, "title", blit_txt=False)
        self.mineffort_msg = message("0%", "normal", blit_txt=False)
        self.maxeffort_msg = message("100%", "normal", blit_txt=False)
        self.submit_msg = message("Continue", "normal", blit_txt=False)
        pad = int(self.submit_msg.height * 0.75)
        self.submit = Button(self.submit_msg,
                             int(self.submit_msg.width + pad * 1.5),
                             self.submit_msg.height + pad,
                             registration=8,
                             location=(P.screen_c[0], int(P.screen_y * 0.8)))

        # Randomly distribute probes across session, avoiding placing them less than 20 sec. apart

        self.probe_trials = []
        noprobe_span = [False] * P.noprobe_span
        probe_span = [True] + [False] * (P.probe_span - 1)
        while len(self.probe_trials) < (P.trials_per_block *
                                        P.blocks_per_experiment):
            random.shuffle(probe_span)
            self.probe_trials += noprobe_span + probe_span

        # Show task instructions and example thought probe

        self.instructions()

        # Add practice blocks to start of task

        self.first_nonpractice = 1
        if P.run_practice_blocks:
            num_nonpractice = P.blocks_per_experiment
            self.insert_practice_block(1,
                                       trial_counts=9,
                                       factor_mask={'number': range(1, 10)})
            self.insert_practice_block(2,
                                       trial_counts=9,
                                       factor_mask={'number': range(1, 10)})
            self.first_nonpractice = P.blocks_per_experiment - num_nonpractice + 1