Example #1
0
 def test_aperture(self):
     win = self.win
     if not win.allowStencil:
         pytest.skip("Don't run aperture test when no stencil is available")
     grating = visual.GratingStim(win,
                                  mask='gauss',
                                  sf=8.0,
                                  size=2,
                                  color='FireBrick',
                                  units='norm')
     aperture = visual.Aperture(win,
                                size=1 * self.scaleFactor,
                                pos=[0.8 * self.scaleFactor, 0])
     aperture.enabled = False
     grating.draw()
     aperture.enabled = True
     str(aperture)  #check that str(xxx) is working
     grating.ori = 90
     grating.color = 'black'
     grating.draw()
     utils.compareScreenshot('aperture1_%s.png' % (self.contextName), win)
     #aperture should automatically disable on exit
     for shape, nVert, pos in [(None, 120, (0, 0)),
                               ('circle', 17, (.2, -.7)),
                               ('square', 4, (-.5, -.5)),
                               ('triangle', 3, (1, 1))]:
         aperture = visual.Aperture(win, pos=pos, shape=shape, nVert=nVert)
         assert len(aperture.vertices) == nVert
         assert aperture.contains(pos)
Example #2
0
 def test_aperture_image(self):
     win = self.win
     fileName = os.path.join(utils.TESTS_DATA_PATH, 'testwedges.png')
     if not win.allowStencil:
         pytest.skip("Don't run aperture test when no stencil is available")
     grating = visual.GratingStim(win,
                                  mask='gauss',
                                  sf=8.0,
                                  size=2,
                                  color='FireBrick',
                                  units='norm')
     aperture = visual.Aperture(win,
                                size=1 * self.scaleFactor,
                                pos=[0.8 * self.scaleFactor, 0],
                                shape=fileName)
     aperture.enabled = False
     grating.draw()
     aperture.enabled = True
     "{}".format(aperture)  #check that str(xxx) is working
     grating.ori = 90
     grating.color = 'black'
     grating.draw()
     utils.compareScreenshot('aperture2_%s.png' % (self.contextName),
                             win,
                             crit=30)
Example #3
0
 def test_aperture(self):
     win = self.win
     if not win.allowStencil:
         pytest.skip("Don't run aperture test when no stencil is available")
     grating = visual.GratingStim(win,
                                  mask='gauss',
                                  sf=8.0,
                                  size=2,
                                  color='FireBrick',
                                  units='norm',
                                  autoLog=False)
     aperture = visual.Aperture(win,
                                size=1 * self.scaleFactor,
                                pos=[0.8 * self.scaleFactor, 0],
                                autoLog=False)
     aperture.disable()
     grating.draw()
     aperture.enable()
     str(aperture)  #check that str(xxx) is working
     grating.setOri(90, log=False)
     grating.setColor('black', log=False)
     grating.draw()
     if utils._under_xvfb:
         pytest.xfail("not clear why fails under Xvfb"
                      )  # skip late so we smoke test t
     utils.compareScreenshot('aperture1_%s.png' % (self.contextName), win)
Example #4
0
def create_stimuli(exp):

    exp.win.allowStencil = True

    aperture = visual.Aperture(
        exp.win,
        exp.p.field_size
    )

    fix = Point(
        exp.win,
        exp.p.fix_pos,
        exp.p.fix_radius,
        exp.p.fix_color
    )

    # TODO incorporate fixation drift warning for training?
    ring = Point(
        exp.win,
        exp.p.fix_pos,
        exp.p.fix_radius * 1.5,
        exp.win.color,
    )

    bar = RetBar(
        exp.win,
        exp.p.field_size,
        exp.p.bar_width,
        exp.p.element_size,
        exp.p.element_tex,
        exp.p.element_sf,
        exp.p.drift_rate,
    )

    return locals()
Example #5
0
    def _setAperture(self):
        """Blocks text beyond border using Aperture

        Returns
        -------
        psychopy.visual.Aperture
            The aperture setting viewable area for forms
        """
        return visual.Aperture(win=self.win, name='aperture',
                               units=self.units, shape='square',
                               size=self.size, pos=(0, 0))
Example #6
0
 def test_aperture(self):
     win = self.win
     if not win.allowStencil:
         pytest.skip("Don't run aperture test when no stencil is available")
     grating = visual.PatchStim(win, mask='gauss',sf=8.0, size=2,color='FireBrick', units='norm')
     aperture = visual.Aperture(win, size=1*self.scaleFactor,pos=[0.8*self.scaleFactor,0])
     aperture.disable()
     grating.draw()
     aperture.enable()
     grating.setOri(90)
     grating.setColor('black')
     grating.draw()
     utils.compareScreenshot('aperture1_%s.png' %(self.contextName), win)
Example #7
0
 def testAperture(self):
     win = self.win
     contextName = self.contextName
     grating = visual.PatchStim(win,
                                mask='gauss',
                                sf=8.0,
                                size=2,
                                color='FireBrick',
                                units='norm')
     aperture = visual.Aperture(win,
                                size=1 * self.scaleFactor,
                                pos=[0.8 * self.scaleFactor, 0])
     aperture.disable()
     grating.draw()
     aperture.enable()
     grating.setOri(90)
     grating.setColor('black')
     grating.draw()
     utils.compareScreenshot('aperture1_%s.png' % (contextName), win)
#Shapes
mask = visual.ShapeStim(win, lineColor='white', fillColor='white', vertices=((-1*stim_width*mask_size_ratio, 0), (0, stim_height*mask_size_ratio), (stim_width*mask_size_ratio, 0), (0,-1*stim_height*mask_size_ratio)))
#mask = visual.Rect(win, lineColor='white', fillColor='white', width = 2*stim_width*1.6, height = 2*stim_height*1.6)
black_square = visual.Rect(win, lineColor='black', fillColor='black', width = 2*stim_width, height = 2*stim_height)


white_diamond = visual.ShapeStim(win, lineColor='white', fillColor='white', vertices=((-1*stim_width, 0), (0, stim_height), (stim_width, 0), (0,-1*stim_height)))
black_diamond = visual.ShapeStim(win, lineColor='black', fillColor='black', vertices=((-1*stim_width-pix_size, 0), (0, stim_height+pix_size), (stim_width+pix_size, 0), (0,-1*stim_height-pix_size)))
blockers = {'left':  visual.ShapeStim(win, lineWidth=.1, lineColor='black', fillColor='black', vertices=((-1, stim_height), (-1, -1*stim_height), (-1*stim_width+stim_width*blocker_size, stim_height), (-1*stim_width+stim_width*blocker_size, -1*stim_height))),
			'right': visual.ShapeStim(win, lineWidth=.1, lineColor='black', fillColor='black', vertices=((1, stim_height), (1, -1*stim_height), (stim_width-stim_width*blocker_size, stim_height), (stim_width-stim_width*blocker_size, -1*stim_height))),
			'top':   visual.ShapeStim(win, lineWidth=.1, lineColor='black', fillColor='black', vertices=((-1, 1), (1, 1), (-1,stim_height-stim_size*blocker_size), (1,stim_height-stim_height*blocker_size))),
			'bottom':visual.ShapeStim(win, lineWidth=.1, lineColor='black', fillColor='black', vertices=((-1, -1), (1, -1), (-1,-1*stim_height+stim_height*blocker_size), (1,-1*stim_height+stim_height*blocker_size)))
			}


apert = visual.Aperture(win, size=1, pos=(0, 0), ori=0, nVert=120, shape=((-1*stim_width, 0), (0, stim_height), (stim_width, 0), (0,-1*stim_height)), inverted=False, units=None, name=None, autoLog=None)
apert.enablaed = False

#aperture = visual.Aperture(win,	size = 1, shape= ((-1*stim_width, 1*stim_height), (-1*stim_width, -1*stim_height), (stim_width, -1*stim_height), (stim_width,1*stim_height)))
#aperture.enabled = False

#maskNoise = visual.ImageStim(win, image = 'maskNoise.png', size = [stim_width*mask_size_ratio*width_ratio, stim_height*mask_size_ratio*height_ratio])
noise = visual.ImageStim(win, image = 'testnoise.png')
#Fixation
fixation = visual.ShapeStim(
				win=win, name='polygon', vertices='cross',
			    size=(stim_width/1.5, stim_height/1.5),
			    ori=0, pos=(0, 0),
			    fillColor=[1,1,1], fillColorSpace='rgb',
				lineColor = [-1,-1,-1],
			    opacity=1, depth=0.0, interpolate=True)
Example #9
0
instr = visual.TextStim(win, text="Any key to quit", pos=(0, -.7))
gabor1 = visual.GratingStim(win,
                            mask='circle',
                            sf=4,
                            size=1.2,
                            color=[0.5, -0.5, 1])
gabor2 = visual.GratingStim(win,
                            mask='circle',
                            sf=4,
                            size=1.2,
                            color=[-0.5, -0.5, -1])
vertices = [(-0.02, -0.0), (-.8, .2), (0, .6), (.1, 0.06), (.8, .3), (.6, -.4)]

# `sizes in Aperture refers to the diameter when shape='circle';
# vertices or other shapes are scaled accordingly
aperture = visual.Aperture(win, size=0.9, shape=vertices)  # try shape='square'
aperture.enabled = False  # enabled by default when created

gabor1.draw()
instr.draw()

# drawing will now only be done within the aperture shape:
aperture.enabled = True
gabor2.draw()

win.flip()
event.waitKeys()

win.close()

# The contents of this file are in the public domain.
Example #10
0
# import psychopy modules
from psychopy import visual, core, event
import numpy as np
# create a window
myWin = visual.Window(size=(800, 600),
                      units="pix",
                      fullscr=False,
                      color=[0, 0, 0],
                      allowStencil=True)
myWin.mouseVisible = False
# create an aperture
myApt = visual.Aperture(myWin, size=100, shape='square')
#create a mouse instance
myMouse = event.Mouse(visible=False)
# prepare the stimuli
text = visual.TextStim(myWin,
                       text="Moving window example " * 32,
                       height=30,
                       color='black',
                       wrapWidth=760)
# mouse-contingent moving window
while True:
    myApt.pos = myMouse.getPos()
    text.draw()
    myWin.flip()
    # press Q to quit the program
    if len(event.getKeys(['q'])):
        myWin.close()
        core.quit()
def main(win, globalClock):

    all_changes = []

    ################################ Stimuli prepation ################################
    globalClock = core.Clock()

    # Make two wedges (in opposite contrast) and alternate them for flashing
    grating_texture = np.tile([[1, -1], [-1, 1]], (8, 8))
    wedge1 = visual.RadialStim(
        win,
        tex=grating_texture,
        color=1,
        units='pix',
        size=win.size[1] * 1.3,
        visibleWedge=[Initial_wedge_pos, Initial_wedge_pos + Wedge_width],
        interpolate=False,
        autoLog=False,
        radialCycles=1,
        angularCycles=4)
    wedge2 = copy.copy(wedge1)
    wedge2.color = -1

    # fixation cross
    fixation = visual.ShapeStim(win,
                                vertices=((0, -1), (0, 1), (0, 0), (-1, 0),
                                          (1, 0)),
                                lineWidth=4,
                                units="pix",
                                size=(20, 20),
                                closeShape=False,
                                lineColor='red',
                                autoDraw=True)

    # Spyder network
    web_circle = visual.Circle(win=win,
                               radius=1,
                               edges=200,
                               units='norm',
                               pos=[0, 0],
                               lineWidth=1,
                               opacity=1,
                               interpolate=True,
                               lineColor=[1.0, 1.0, 1.0],
                               lineColorSpace='rgb',
                               fillColor=None,
                               fillColorSpace='rgb')
    web_dimension = (screenCorrection(win, Web_size[0]), Web_size[1])
    web_line = visual.Line(win,
                           name='Line',
                           start=(-1.4, 0),
                           end=(1.4, 0),
                           pos=[0, 0],
                           lineWidth=1,
                           lineColor=[1.0, 1.0, 1.0],
                           lineColorSpace='rgb',
                           opacity=1,
                           interpolate=True)

    # DEBUG stimuli
    if DEBUG_MODE:
        fps_text = visual.TextStim(win,
                                   units='norm',
                                   height=0.05,
                                   pos=(-0.98, +0.93),
                                   text='starting...',
                                   font=sans,
                                   alignHoriz='left',
                                   alignVert='bottom',
                                   color='yellow')
        fps_text.autoDraw = True

        orientation_details_string = visual.TextStim(win,
                                                     text=u"eccentricity..",
                                                     units='norm',
                                                     height=0.05,
                                                     pos=(0.95, +0.93),
                                                     alignHoriz='right',
                                                     alignVert='bottom',
                                                     font=sans,
                                                     color='yellow')
        orientation_details_string.autoDraw = True

    # External Aperture (black ring)
    external_aperture_size = tuple(
        [screenCorrection(win, External_ring_size), External_ring_size])
    external_aperture = visual.Aperture(win,
                                        size=external_aperture_size,
                                        shape='circle')
    external_aperture.enabled = False

    ################################ Definitions/Functions ################################

    ## handle Rkey presses each frame
    def escapeCondition(which_key):
        for key in event.getKeys():
            if key in ['escape', 'q', which_key]:
                return False
        return True

    ################################ Animation starts ################################
    # display instructions and wait
    message1 = visual.TextStim(win, pos=[0, 0.5], text='Hit a key when ready.')
    message1.draw()
    fixation.draw()
    win.flip()
    event.waitKeys()  #pause until there's a keypress

    # Scanner trigger wait
    message3 = visual.TextStim(win,
                               pos=[0, 0.25],
                               text=scanner_message,
                               font=serif,
                               alignVert='center',
                               wrapWidth=1.5)
    message3.size = .5
    message3.draw()
    win.flip()

    if BUTTON_BOX:
        button_state = button_thread.button_state
        while 1:
            if (button_state['state'][-1] == 0):
                break
            if escapeCondition('f') == False: break
    else:
        event.waitKeys()  #pause until there's a keypress

    # Wait Pre_post_stimuli_fixation_time before stimuli
    # Spyder network
    if Spyder_grid:
        for i_dim in range(Spyder_rings):
            web_circle.setSize(
                tuple([
                    x * (i_dim + 1) * 1. / Spyder_rings for x in web_dimension
                ]))
            web_circle.draw()
        for i_dim in range(2):
            web_line.setOri(i_dim * 90)
            web_line.draw()
    win.flip()
    core.wait(Pre_post_stimuli_fixation_time)

    t = i_cycle = last_fps_update = 0
    break_flag = True
    globalClock.reset()
    inizio = globalClock.getTime()
    logging.data('First cycle. Number %d/%d at %f (sec.)' %
                 (i_cycle + 1, Cycles_number, inizio))

    while (globalClock.getTime() < Total_time and break_flag == True):
        t = globalClock.getTime()

        # Spyder network
        if Spyder_grid:
            for i_dim in range(Spyder_rings):
                web_circle.setSize(
                    tuple([
                        x * (i_dim + 1) * 1. / Spyder_rings
                        for x in web_dimension
                    ]))
                web_circle.draw()
            for i_dim in range(2):
                web_line.setOri(i_dim * 90)
                web_line.draw()

        # External ring
        external_aperture.enabled = True

        # Setup stimulus
        if t % Flash_period < Flash_period / 2.0:  # more accurate to count frames
            stim = wedge1
        else:
            stim = wedge2
        stim.ori = -t * Rotation_rate * 360.0  # set new rotation
        stim.draw()

        # Fixation
        if Rotating_cross:
            fixation.ori = t * Rotation_cross_rate * 360.0  # set new rotation
        if Color_change_cross:
            if t % Color_change_rate < Color_change_rate / 2.0:  # more accurate to count frames
                fixation.lineColor = 'red'
            else:
                fixation.lineColor = 'green'

        if (t >= ((i_cycle + 1) * 1 / Rotation_rate)):
            logging.data('Change orientation. Number %d/%d at %f (sec.)' %
                         (i_cycle + 1, Cycles_number, t))
            new_record = globalClock.getTime() - sum(all_changes)
            all_changes.append(new_record)
            i_cycle += 1

        external_aperture.enabled = False

        if DEBUG_MODE:
            if t - last_fps_update > Fps_update_rate:  # update the fps text every second
                fps_text.text = "%.2f fps" % win.fps()
                last_fps_update += 1
            orientation_details_string.text = 'Pass: %d/%d at %.3f (sec.)' % (
                i_cycle + 1, Cycles_number, np.sum(all_changes))

        win.flip()
        break_flag = escapeCondition('f')
        if break_flag == False: break

    logging.data('Total time spent: %.6f' % (globalClock.getTime() - inizio))
    logging.data('Every frame duration saved in %s' %
                 (path_out + Frames_durations_name))
    logging.data('All durations: ' + str(all_changes))
    logging.data('Mean: ' +
                 str(sum(all_changes) / (len(all_changes) + EPSILON)))

    if DEBUG_MODE:
        orientation_details_string.text = 'Ended at %.3f (sec.)' % (
            globalClock.getTime())

    win.flip()
    # Wait Pre_post_stimuli_fixation_time after stimuli
    core.wait(Pre_post_stimuli_fixation_time)
    return
Example #12
0
def manual_events(recording_path,
                  trial_duration,
                  skiptime=0,
                  events={},
                  bracket="",
                  volume=1.,
                  output_path="~/evaluation",
                  non_redundant=True):
    """Evaluate a behavioural recording.
	E.g. for forced swim test, press enter when the experiment starts and s/i to annotate the onset of the respective behaviours.
	!!! Add optional instructons screen !!!
	Mention e.g. that you need to press return to start the evaluation period.

	Parameters
	----------
	recording_path: str
		Path to the recording file.
	trial_duration: int
		Number of seconds the trial should last after pressing the evaluation start key.

	"""

    recording_path = os.path.expanduser(recording_path)
    csv_output_path = os.path.expanduser(output_path) + ".csv"

    if os.path.exists(csv_output_path):
        print("There is already an evaluation file at " + csv_output_path +
              ". Please specify a different output path.")
        return

    keylist = ['left', 'right', 'up', 'down', 'escape', 'return']
    experiment_keylist = events.keys()
    keylist.extend(experiment_keylist)

    #process brackets string
    x_y_brackets = bracket.split(",")
    if len(x_y_brackets) == 1 and x_y_brackets != [""]:
        x0, x1 = [float(i) / 100 for i in x_y_brackets[0].split("-")]
        y0 = 0.
        y1 = 1.
    elif len(x_y_brackets) == 2:
        try:
            x0, x1 = [float(i) / 100 for i in x_y_brackets[0].split("-")]
        except ValueError:
            x0 = 0.
            x1 = 1.
        try:
            y0, y1 = [float(i) / 100 for i in x_y_brackets[1].split("-")]
        except ValueError:
            y0 = 0.
            y1 = 1.
    else:
        x0 = y0 = 0.
        x1 = y1 = 1.

    win = visual.Window(
        size=(2048, 1152),
        fullscr=True,
        screen=0,
        allowGUI=False,
        allowStencil=True,
        monitor='testMonitor',
        color=[0, 0, 0],
        colorSpace='rgb',
        blendMode='avg',
        useFBO=True,
        units="norm",
    )

    # Initialize components for Routine "trial"
    trialClock = core.Clock()
    mov = visual.MovieStim3(
        win=win,
        name='mov',
        filename=recording_path,
        depth=0.0,
        volume=volume,
        units="norm",
    )

    #set full_movie dimensions based on aspect ratio (making one value from each operation float to ensure float division)
    if float(mov.size[0]) / mov.size[1] < float(win.size[0]) / win.size[1]:
        full_movie_y = 2.
        full_movie_x = 2 * float(
            win.size[1]) / win.size[0] / (float(mov.size[1]) / mov.size[0])
    else:
        full_movie_y = 2 * float(
            win.size[1]) / win.size[0] / (float(mov.size[1]) / mov.size[0])
        full_movie_x = 2.
    mov.size = (full_movie_x, full_movie_y)

    #position video so as to center bracket
    mov_xsize, mov_ysize = mov.size
    movsection_xpos = (x0 + x1) / 2.
    movsection_ypos = (y0 + y1) / 2.
    mov_xpos = mov_xsize * (1. / 2. - movsection_xpos)
    mov_ypos = mov_ysize * (1. / 2. - movsection_ypos)
    mov.pos = (mov_xpos, mov_ypos)

    #set aperture to bracket
    movsection_xsize = x1 - x0
    movsection_ysize = y1 - y0
    aperture_x = movsection_xsize * mov_xsize
    aperture_y = movsection_ysize * mov_ysize
    aperture = visual.Aperture(win,
                               size=(aperture_x, aperture_y),
                               pos=(0, 0),
                               ori=0,
                               nVert=120,
                               shape='square',
                               inverted=False,
                               name=None,
                               autoLog=None)

    # Create some handy timers
    globalClock = core.Clock()  # to track the time since measurement started
    trialClock = core.Clock()  # to track the time since measurement started
    routineTimer = core.CountdownTimer(
    )  # to track time remaining in the experiment

    # prepare evaluation variables
    mov.status = NOT_STARTED
    pre_evaluation = True
    outputWriter1 = csv.writer(open(csv_output_path, 'w'), lineterminator='\n')
    outputWriter1.writerow(["start", "behaviour"])
    lastkey = ""

    # Start evaluation
    globalClock.reset()
    while pre_evaluation or routineTimer.getTime() > 0:
        T = globalClock.getTime()
        t = trialClock.getTime()
        resp_key = event.getKeys(keyList=keylist)
        if pre_evaluation:
            if "return" in resp_key:
                trialClock.reset()
                routineTimer.reset()
                routineTimer.add(trial_duration)
                pre_evaluation = False
        elif resp_key:
            if resp_key[0] in experiment_keylist:
                if non_redundant and resp_key[0] == lastkey:
                    pass
                else:
                    tempArray = [t, events[resp_key[0]]]
                    outputWriter1.writerow(tempArray)
                    tempArray = []  # make sure no info persists
                    lastkey = resp_key[0]

        #start movie and keep track of start time
        if t >= 0.0 and mov.status == NOT_STARTED:
            mov.tStart = T
            mov.setAutoDraw(True)

        if mov.status == FINISHED:
            break

        # check for quit (the Esc key)
        if "escape" in resp_key:
            outputWriter1.writerow([t, "QUIT"])
            core.quit()

        win.flip()

    outputWriter1.writerow([t, "END"])
    if mov.status != FINISHED:
        mov.setAutoDraw(False)
    win.close()
    return
Example #13
0
    )
else:
    tk.sendCommand(
        "file_sample_data  = LEFT,RIGHT,GAZE,AREA,GAZERES,STATUS,INPUT")
    tk.sendCommand(
        "link_sample_data  = LEFT,RIGHT,GAZE,GAZERES,AREA,STATUS,INPUT")

# STEP VI: specify all possible experimental cells & prepare the visual stimuli
# one may read in a spreadsheet containing all the experimentl cells; usually, a simple list
# should also do the job; if we need tweenty trials, simple go with "new_list = trials[:]*10", then
# random.shuffle(new_list)

trials = [['mask', 'sacrmeto.jpg'], ['window', 'sacrmeto.jpg']]

# prepare a circular aperture as a gaze-contingent window
gazeWindow = visual.Aperture(win, size=200)
gazeWindow.enabled = False
# prepare a gaze-contingent mask
gazeMask = visual.GratingStim(win,
                              tex='none',
                              mask='circle',
                              size=200,
                              color=[1.0, 1.0, 1.0])


# SETP VII: a couple of helpers
def runTrial(pars):
    """ pars corresponds to a row in the trial list"""

    # retrieve paramters from the trial list, in the "mask" condition we simply draw mask
    #at the current gaze position
Example #14
0
from psychopy import visual, core, event

win = visual.Window([400, 400], allowStencil=True, units='norm')
gabor1 = visual.GratingStim(win,
                            mask='circle',
                            pos=[0.2, 0.2],
                            sf=4,
                            size=.4,
                            color=[0.5, -0.5, 1])
gabor2 = visual.GratingStim(win,
                            mask='circle',
                            pos=[-0.2, -0.2],
                            sf=4,
                            size=.4,
                            color=[-0.5, -0.5, -1])

aperture = visual.Aperture(win, size=.5, pos=[0.16, 0.16], shape='square')
aperture.enable()  #actually is enabled by default when created
gabor1.draw()
aperture.disable()  #drawing from here ignores aperture
gabor2.draw()

win.flip()
event.waitKeys()
Example #15
0
def main(argv=sys.argv):

    data_dir_root = '/Users/Eichenbaum/HWNI/Experiments/HRL_Geometry/scripts/psychopy'  #'/Users/despolabtesting1/Desktop/Experiments/eichenbaum/HRL_Geo_Barker135' # '/Users/StimulusMac/Desktop/Experiments/DespoLab/adameich/HRL'

    d = 57  # Distance between monitor and participant in cm  ## This scales everything that is coded in degrees!
    my_monitor = monitors.Monitor(name='DesktopLab')
    my_monitor.setSizePix(
        (1920, 1080)
    )  # (2560,1440) (1024, 768) (1920,1080)## This scales everything that is coded in degrees!
    my_monitor.setDistance(
        d)  ## This scales everything that is coded in degrees!
    my_monitor.setWidth(
        50.88)  ## This scales everything that is coded in degrees!
    my_monitor.saveMon()

    monitor = 'DesktopLab'
    res = [1024, 768]  # [1920,1080] [1024, 768]

    ####################
    ### Subject Info ###
    ####################
    SubID = str(sys.argv[1])
    Age = int(sys.argv[2])
    Gen = str(sys.argv[3])
    Run = int(sys.argv[4])
    Date = str(data.getDateStr())

    CounterBalanceNumber = int(SubID) % 4
    if Run % 2 == 1:
        flipOrder = False  #(AB)
        flipOrderStr = 'AB'
    elif Run % 2 == 0:
        flipOrder = True  #(BA)
        flipOrderStr = 'BA'
    print(flipOrder, flipOrderStr)
    win = visual.Window(res,
                        fullscr=False,
                        monitor=monitor,
                        color=[-.375, -.375, -.375],
                        units='deg',
                        allowStencil=True)

    # Shared Parameter Values#
    h = 28.62  # 34.544#3.6221171854 # Monitor height in cm
    r = win.size[1]  # Vertical resolution of the monitor
    deg_per_px = degrees(atan2(.5 * h, d)) / (
        .5 * r
    )  # Calculate the number of degrees that correspond to a single pixel. This will generally be a very small value, something like 0.03.

    #########################################################################
    ######## Data file creation for trial info and user response info #######
    #########################################################################
    file_name = SubID + '_HRL_Geo_Run_' + str(Run)
    complete_file_name = os.path.join(data_dir_root, 'data',
                                      file_name + '.csv')
    HRLDataFile = open(complete_file_name, 'w')
    firstLine = [
        'DateTime',  ### The Date and Time at the start of the session.
        'SubID',  ### The 3-digit numeric code given to the participant
        'Gen',  ### One of three options: M = 'Male', F = 'Female', O = 'Other'
        'Age',  ### The age of the participant
        'Run',  ### The current block of the expt (currently set to 5 blocks)
        'CntrBalNum',  ### CounterBalanceNumber
        'StimSet',  ### Which of the two stimulus sets are they seeing?
        'RuleOrder',  ### OVERALL SoT-CoT or CoT-SoT
        'FlipRunOrder',  ### Within this run, is the RuleOrder going to be normal (AB) or flipped (BA)?
        'RunOrderStr',  ### The actual string of "AB" or "BA"
        'Trial',  ### Trial number 
        'ShapeName',  ### The shape stimulus that was shown on the current trial. Will be a string.
        'ShapeNumber',  ### The 0 or 1 in the design matrix
        'ColorName',  ### The color of the border that was shown on the current trial. Will be a string. 
        'ColorNumber',  ### The 0 or 1 in the design matrix
        'TextureName',  ### The texture image that was shown on the current trial. Will be an integer.
        'TextureNumber',  ### The 0 or 1 in the design matrix
        'Rule',  ### Shape-on-Top or Color-on-Top
        'StimIdx',  ### The number associated with that stimulus conjunction. This will be a good cross check to make sure that everything is coding appropriately for e.g. numSince
        'Iter',  ### Provides how many times the stimulus conjuction has been previously seen this block. 
        'Response',  ### The keyboard input provided by the Pp for the current trial. Will be a string of either '1', '2', '3', or '4', or 'NaN' if no input detected.
        'tAns',  ### The correct answer for the current trial. Will be a string of either 'v', 'b', 'n', or 'm'.
        'tOut',  ### Whether the response was Correct (1), Incorrect (-1), or No Response provided ('Nan') 
        'TrialRT',  ### Reaction time from Stimulus onset to response. Will be a float. If no response provided, will be a "NaN" string. 
        'PlannedITI',
        'StimDur',
        'StimOnset',  ### The time when the stimulus is presented on screen, relative the the first TTL pulse. 
        'RespOnset',  ### The time when the first button press response to the stimulus occured, relative to the first TTL pulse received. 
        'StimOffset',  ### The time when the stimulus goes off screen (should be identical to "confOff")
        'ITIOn'
    ]
    firstLine = ','.join(firstLine)
    HRLDataFile.write(firstLine + '\n')

    ########################
    ## Drawing Parameters ##
    ########################
    wrapWidth = 22.5
    line_width_val = 0.0
    stim_rad = 5.0 * .8
    opa_val = 1.0
    rect_width = 10.0 * .8
    rect_height = 10.0 * .8
    size = .4  # How large everything will be from the aperture perspective
    border_size_boost = 1.3
    text_win_size = .55

    ### Colors ###
    RGB_colors = (np.array([(255, 0, 0), (0, 0, 255), (255, 255, 0),
                            (255, 0, 255)]) - 127.5) / 127.5
    tutorial_colors = (np.array([(0, 255, 0), (0, 0, 128)]) - 127.5) / 127.5
    rgbNames = np.array(['red', 'blue', 'yellow', 'magenta'])

    ### Texture Images used ###
    texIdx_array = np.array((11, 37, 65, 87))

    ###############################
    ## Block Creation Parameters ##
    ###############################
    nDims = 3
    nTrials = 32

    #######################
    ## Timing Parameters ##
    #######################
    fmri_wait_time = 5
    schematicViewTime = 15
    RespDurLimit = 2.0  # 120 frames will allow the subject to respond within a 2000ms window.

    myOverallClock = core.Clock(
    )  # clock used for overal stimulus timing throughout the experiment
    TTL_start_clock = core.Clock()
    timingClock = core.Clock()

    StimOnset = np.ones(nTrials) * np.nan
    ITIOn = np.ones(nTrials) * np.nan

    ITI_base = [5, 6, 6, 7]
    ITIs_tmp_a = []
    ITIs_tmp_b = []
    ITIs_tmp_a = np.tile(ITI_base, [4])
    ITIs_tmp_b = np.tile(ITI_base, [4])
    np.random.shuffle(ITIs_tmp_a)
    np.random.shuffle(ITIs_tmp_b)
    ITIs = np.hstack((ITIs_tmp_a, ITIs_tmp_b))

    #########################
    ## Response Parameters ##
    #########################
    keyState = key.KeyStateHandler()
    win.winHandle.push_handlers(keyState)
    answer_keys_bBox = ['1', '2', '3', '4']
    answer_keys = ['v', 'b', 'n', 'm']
    totalCorrect = 0

    ########################
    ##  Circle Stimulus   ##
    ########################
    circle = visual.Circle(win,
                           size=size,
                           radius=stim_rad,
                           units='deg',
                           lineWidth=line_width_val,
                           edges=256,
                           opacity=opa_val,
                           interpolate=True,
                           name='circle')
    circle2 = visual.Circle(win,
                            size=size * border_size_boost * 0.9,
                            radius=stim_rad,
                            units='deg',
                            lineWidth=line_width_val,
                            edges=256,
                            opacity=opa_val,
                            interpolate=True)
    circle3 = visual.Circle(win,
                            size=size * 0.8,
                            radius=stim_rad,
                            units='deg',
                            lineWidth=line_width_val,
                            edges=256,
                            opacity=opa_val,
                            interpolate=True)
    ########################
    ##  Square Stimulus   ##
    ########################
    square = visual.Rect(win,
                         size=size,
                         width=rect_width,
                         height=rect_height,
                         units='deg',
                         lineWidth=line_width_val,
                         opacity=opa_val,
                         interpolate=True,
                         name='square')
    square2 = visual.Rect(win,
                          size=size * border_size_boost * 0.9,
                          width=rect_width,
                          height=rect_height,
                          units='deg',
                          lineWidth=line_width_val,
                          opacity=opa_val,
                          interpolate=True)
    square3 = visual.Rect(win,
                          size=size * .8,
                          width=rect_width,
                          height=rect_height,
                          units='deg',
                          lineWidth=line_width_val,
                          opacity=opa_val,
                          interpolate=True)
    ########################
    ## Triangle Stimulus  ##
    ########################
    triangle = visual.Polygon(win,
                              size=size,
                              edges=3.0,
                              radius=6.0,
                              units='deg',
                              pos=(0, -.1),
                              lineWidth=line_width_val,
                              opacity=opa_val,
                              interpolate=True,
                              name='triangle')
    triangle2 = visual.Polygon(win,
                               size=size * border_size_boost * .95,
                               edges=3.0,
                               radius=6.0,
                               units='deg',
                               pos=(0, -.1),
                               lineWidth=line_width_val,
                               opacity=opa_val,
                               interpolate=True)
    triangle3 = visual.Polygon(win,
                               size=size * .8,
                               edges=3.0,
                               radius=6.0,
                               units='deg',
                               pos=(0, -.25),
                               lineWidth=line_width_val,
                               opacity=opa_val,
                               interpolate=True)
    ########################
    ## Pentagon Stimulus  ##
    ########################
    pentagon = visual.Polygon(win,
                              size=size,
                              edges=5.0,
                              radius=stim_rad,
                              units='deg',
                              lineWidth=line_width_val,
                              opacity=opa_val,
                              interpolate=True,
                              name='pentagon')
    pentagon2 = visual.Polygon(win,
                               size=size * border_size_boost * 0.925,
                               edges=5.0,
                               radius=stim_rad,
                               units='deg',
                               lineWidth=line_width_val,
                               opacity=opa_val,
                               interpolate=True)
    pentagon3 = visual.Polygon(win,
                               size=size * .8,
                               edges=5.0,
                               radius=stim_rad,
                               units='deg',
                               lineWidth=line_width_val,
                               opacity=opa_val,
                               interpolate=True)
    #####################
    ## Wash-out Filter ##
    #####################
    washOut_Filter = visual.Rect(win,
                                 width=win.size[0],
                                 height=win.size[1],
                                 units='pix',
                                 lineWidth=line_width_val,
                                 fillColor=[1, 1, 1],
                                 opacity=.1,
                                 interpolate=True)

    #####################
    ## (Tut.)  Diamond ##
    #####################
    vees = np.ones((4, 2)) * np.nan
    for idx, tmp in enumerate([0, 90, 180, 270]):
        vees[idx, 0] = ((5 * np.sqrt(2)) * np.sin(np.deg2rad(tmp)))
        vees[idx, 1] = ((5 * np.sqrt(2)) * np.cos(np.deg2rad(tmp)))
    diamond = visual.Rect(win,
                          size=size * .8,
                          width=rect_width,
                          height=rect_height,
                          units='deg',
                          lineWidth=line_width_val,
                          opacity=opa_val,
                          ori=45.0,
                          interpolate=True,
                          name='diamond')
    diamond2 = visual.Rect(win,
                           size=.9 * (size * border_size_boost * 0.95),
                           width=rect_width,
                           height=rect_height,
                           units='deg',
                           lineWidth=line_width_val,
                           opacity=opa_val,
                           ori=45.0,
                           interpolate=True)
    #####################
    ## (Tut.)  Octagon ##
    #####################
    octagon = visual.Polygon(win,
                             size=size,
                             edges=8.0,
                             radius=stim_rad,
                             units='deg',
                             lineWidth=line_width_val,
                             opacity=opa_val,
                             interpolate=True,
                             name='pentagon')
    octagon2 = visual.Polygon(win,
                              size=size * border_size_boost * 0.9,
                              edges=8.0,
                              radius=stim_rad,
                              units='deg',
                              lineWidth=line_width_val,
                              opacity=opa_val,
                              interpolate=True)

    ### Create Fixation Cross ###
    fixation1w = visual.Line(win,
                             units='deg',
                             start=(0, -0.35),
                             end=(0, 0.35),
                             lineColor='white',
                             lineWidth=4)
    fixation2w = visual.Line(win,
                             units='deg',
                             start=(-0.35, 0),
                             end=(0.35, 0),
                             lineColor='white',
                             lineWidth=4)

    ### Shapes ###
    shape_list = [circle, square, triangle, pentagon]
    shape_list2 = [circle2, square2, triangle2, pentagon2]
    shape_list3 = [circle3, square3, triangle3, pentagon3]
    Shape_list_wTut = [octagon, diamond]
    Shape_list_wTut2 = [octagon2, diamond2]

    if CounterBalanceNumber in [0, 2]:
        StimSet = 1  # Circle-Triangle, Blue-Yellow
    else:
        StimSet = 2  # Square-Pentagon, Red-Pink

    if CounterBalanceNumber == 0:
        CB_vals = [1, 2]
        currShapeList1 = [circle, triangle]
        currShapeList2 = [circle2, triangle2]
        currShapeList3 = [circle3, triangle3]
        order = 0  # Sot-Cot

    elif CounterBalanceNumber == 1:
        CB_vals = [0, 3]
        currShapeList1 = [square, pentagon]
        currShapeList2 = [square2, pentagon2]
        currShapeList3 = [square3, pentagon3]
        order = 0  # Sot-Cot

    elif CounterBalanceNumber == 2:
        CB_vals = [1, 2]
        currShapeList1 = [circle, triangle]
        currShapeList2 = [circle2, triangle2]
        currShapeList3 = [circle3, triangle3]
        order = 1  # Cot-Sot

    elif CounterBalanceNumber == 3:
        CB_vals = [0, 3]
        currShapeList1 = [square, pentagon]
        currShapeList2 = [square2, pentagon2]
        currShapeList3 = [square3, pentagon3]
        order = 1  # Cot-Sot

    currTexList = texIdx_array[CB_vals]
    currColList = RGB_colors[CB_vals]
    currColNameList = rgbNames[CB_vals]

    ##########################################################################
    ## Construct General Trial Array for Rule / Context #1 ==> Shape on Top ##
    ##########################################################################
    trialArray_SoT = np.zeros((2**nDims, 5)) * np.nan
    trialArray_SoT[:, 0] = [0, 0, 0, 0, 1, 1, 1, 1]  # Shape
    trialArray_SoT[:, 1] = [0, 0, 1, 1, 0, 0, 1, 1]  # Color
    trialArray_SoT[:, 2] = [0, 1, 0, 1, 0, 1, 0, 1]  # Texture
    trialArray_SoT[:, 3] = [0, 0, 2, 2, 1, 3, 1, 3]  # Answer #
    trialArray_SoT[:, 4] = [0, 1, 2, 3, 4, 5, 6, 7]  # Unique Stim ID

    ##########################################################################
    ## Construct General Trial Array for Rule / Context #2 ==> Color on Top ##
    ##########################################################################
    trialArray_CoT = np.zeros((2**nDims, 5)) * np.nan
    trialArray_CoT[:, 0] = [0, 0, 0, 0, 1, 1, 1, 1]  # Shape
    trialArray_CoT[:, 1] = [0, 0, 1, 1, 0, 0, 1, 1]  # Color
    trialArray_CoT[:, 2] = [0, 1, 0, 1, 0, 1, 0, 1]  # Texture
    trialArray_CoT[:, 3] = [2, 1, 3, 3, 2, 1, 0, 0]  # Answer
    trialArray_CoT[:, 4] = [0, 1, 2, 3, 4, 5, 6, 7]  # Unique Stim ID

    ###########################
    ## Construct Trial Array ##
    ###########################
    trialArray_SoT_Total = np.zeros(
        (trialArray_SoT.shape[0] * 2, trialArray_SoT.shape[1])) * np.nan
    tmp_SoT_a = []
    tmp_SoT_a = np.tile(trialArray_SoT[:, :], [2, 1])
    np.random.shuffle(tmp_SoT_a)
    trialArray_SoT_Total[0:16, :] = tmp_SoT_a

    trialArray_CoT_Total = np.zeros(
        (trialArray_CoT.shape[0] * 2, trialArray_CoT.shape[1])) * np.nan
    tmp_CoT_a = []
    tmp_CoT_a = np.tile(trialArray_CoT[:, :], [2, 1])
    np.random.shuffle(tmp_CoT_a)
    trialArray_CoT_Total[0:16, :] = tmp_CoT_a

    Full_Trial_Array = np.zeros((nTrials, 5)) * np.nan

    if CounterBalanceNumber in [0, 1]:
        if flipOrder:
            Full_Trial_Array[0:16, :] = trialArray_CoT_Total
            Full_Trial_Array[16:32, :] = trialArray_SoT_Total
            stringCurrRule1 = 'Color-on-Top'
            stringCurrRule2 = 'Shape-on-Top'
        else:
            Full_Trial_Array[0:16, :] = trialArray_SoT_Total
            Full_Trial_Array[16:32, :] = trialArray_CoT_Total
            stringCurrRule1 = 'Shape-on-Top'
            stringCurrRule2 = 'Color-on-Top'

    elif CounterBalanceNumber in [2, 3]:
        if flipOrder:
            Full_Trial_Array[0:16, :] = trialArray_SoT_Total
            Full_Trial_Array[16:32, :] = trialArray_CoT_Total
            stringCurrRule1 = 'Shape-on-Top'
            stringCurrRule2 = 'Color-on-Top'
        else:
            Full_Trial_Array[0:16, :] = trialArray_CoT_Total
            Full_Trial_Array[16:32, :] = trialArray_SoT_Total
            stringCurrRule1 = 'Color-on-Top'
            stringCurrRule2 = 'Shape-on-Top'

    #######################################################
    ### Build Trial Duration and Trial Start-Time Array ###
    #######################################################
    trial_durations = (np.ones(nTrials) * RespDurLimit) + ITIs
    trial_starts_matrix = np.ones((nTrials)) * np.nan

    for i in range(nTrials):
        if i == 0:
            trial_starts_matrix[i] = 0
        else:
            trial_starts_matrix[i] = (trial_starts_matrix[i - 1] +
                                      trial_durations[i - 1])

    trial_starts_matrix += fmri_wait_time
    trial_starts_matrix += 2  # The amount of time the 1st rule is on screen
    trial_starts_matrix += 7  # The ITI between the 1st Rule going off screen and Trial #1 starting
    trial_starts_matrix[
        16:32] += 2  # The amount of time the 2nd rule is on screen
    trial_starts_matrix[
        16:
        32] += 7  # The ITI between the 2nd Rule going off screen and Trial #33 starting

    print(trial_starts_matrix)
    win.mouseVisible = False
    experimentStart = myOverallClock.getTime()

    ######################################
    ######### INSTRUCTIONS START #########
    ######################################
    if CounterBalanceNumber in [0, 2]:
        schematicSoT = "Schematic_1_SoT.tiff"
        schematicCoT = "Schematic_1_CoT.tiff"
    else:
        schematicSoT = "Schematic_2_SoT.tiff"
        schematicCoT = "Schematic_2_CoT.tiff"

    for i in range(schematicViewTime):
        visual.TextStim(win,
                        height=text_win_size,
                        wrapWidth=wrapWidth,
                        text='RULE REMINDER       [%s] seconds remain' %
                        (str(schematicViewTime - i))).draw()
        visual.ImageStim(win, image=schematicSoT, pos=[0, 6]).draw()
        visual.ImageStim(win, image=schematicCoT, pos=[0, -6]).draw()
        win.flip()
        core.wait(1)

    visual.TextStim(win,
                    height=text_win_size,
                    wrapWidth=wrapWidth,
                    text='We are now starting the task.\n\n\
No feedback will be provided after each response. Instead you will be told of your overall accuracy at the end of each run.\n\n\
Press Any Key to Begin').draw()
    win.flip()
    core.wait(1)
    event.waitKeys()

    #######################
    ### Waiting for TTL ###
    #######################
    visual.TextStim(
        win,
        height=text_win_size,
        wrapWidth=wrapWidth,
        text=
        'Scanner is warming up and making adjustments. It is crucial that you stay as still as you can.'
    ).draw()
    win.flip()

    event.waitKeys(keyList='5')

    fixation1w.draw(), fixation2w.draw()
    win.flip()

    TTL_start_clock.reset()

    core.wait(fmri_wait_time)

    #################################
    ### Display text for 1st Rule ###
    #################################
    currentRule = stringCurrRule1
    visual.TextStim(win,
                    height=text_win_size,
                    wrapWidth=wrapWidth,
                    text='CURRENT RULE\n\n\
%s' % (stringCurrRule1)).draw()
    win.flip()
    core.wait(2)
    win.flip()
    core.wait(7)

    ########################
    ### START TRIAL LOOP ###
    ########################
    for trial in np.arange(Full_Trial_Array.shape[0]):
        buttonPressed = None
        resp, Resp1Time, Response1_On = False, False, False

        ####################################
        ### Display text for Rule Change ###
        ####################################
        if trial == 16:
            currentRule = stringCurrRule2
            visual.TextStim(win,
                            height=text_win_size,
                            wrapWidth=wrapWidth,
                            text='RULE CHANGE\n\n\
%s' % (stringCurrRule2)).draw()
            win.flip()
            core.wait(2)
            win.flip()
            core.wait(7)

        #########################################################################
        ### Determine which shape, color, texture will be drawn on this trial ###
        #########################################################################
        shape_val = currShapeList1[Full_Trial_Array[trial, 0].astype(int)]
        shape_val_brd = currShapeList2[Full_Trial_Array[trial, 0].astype(int)]

        shape_val.setPos([0, 0])
        shape_val_brd.setPos([0, 0])

        ### Create the Texture Visual Patch ###
        imgstim = visual.ImageStim(
            win=win,
            pos=shape_val.pos,
            size=[10, 10],
            image=os.path.join(
                data_dir_root, 'Normalized_Brodatz/D%s.tif' %
                (currTexList[Full_Trial_Array[trial, 2].astype(int)])))

        ### Fill the to-be Border Shape with the current trial's color ###
        shape_val_brd.setFillColor(
            currColList[Full_Trial_Array[trial, 1].astype(int), :], 'rgb')

        ### Create the aperture so that the texture seen is only in the size and shape of the current shape ###
        aperture = visual.Aperture(win,
                                   size=size,
                                   shape=shape_val.vertices,
                                   pos=shape_val.pos)
        aperture.enabled = False

        ###############################################
        ### Waiting for previous trial's ITI to end ###
        ###############################################
        while TTL_start_clock.getTime() < trial_starts_matrix[trial]:
            pass

        ##############################
        ### Start Drawing Stimulus ###
        ##############################
        event.clearEvents()
        Pres_stim(shape_val_brd, aperture, imgstim, washOut_Filter)
        win.flip()
        StimOnset[trial] = TTL_start_clock.getTime(
        )  #The stimulus has just been shown. Onset time is measured as the first moment after the window was flipped

        timingClock.reset()
        while timingClock.getTime() <= RespDurLimit:
            if resp:
                break
            if not resp:
                allKeys = event.getKeys()

                ### Check to see if the response made is one of the allowable responses
                for thisKey in allKeys:
                    if thisKey in answer_keys_bBox:
                        Resp1Time = timingClock.getTime(
                        )  # Within Trial time of response to the stimulus
                        Response1_On = TTL_start_clock.getTime(
                        )  # Time of response to the stimulus relative to the start of the 1st TTL pulse
                        if thisKey == answer_keys_bBox[Full_Trial_Array[
                                trial, 3].astype(int)]:
                            resp, buttonPressed = 1, thisKey  #Correct
                            totalCorrect += 1
                        else:
                            resp, buttonPressed = -1, thisKey  #Incorrect
                    if thisKey in ['escape']:
                        win.close()
                        core.quit()

        ##########################################################
        ### Remove Stimulus from Screen after full 2s duration ###
        ##########################################################
        while timingClock.getTime() <= RespDurLimit:
            pass
        win.flip()
        stimOffset = TTL_start_clock.getTime(
        )  # This stimulus has just left the screen. The ITI has begun.

        #################################
        ### Intertrial Interval Start ###
        #################################
        ITIOn[trial] = TTL_start_clock.getTime()
        if trial != Full_Trial_Array.shape[0] - 1:
            fixation1w.draw(), fixation2w.draw()
            win.flip()

        iteration = list(Full_Trial_Array[:trial, 4]).count(
            Full_Trial_Array[trial, 4]) + 1
        stimDur = stimOffset - StimOnset[trial]

        ##########################################################################
        ### Data file update for trial & user response info: Saved every trial ###
        ##########################################################################
        trialDataArray = map(
            str,
            [
                Date,  # DateTime
                SubID,  # SubID
                Gen,  # Gen
                Age,  # Age
                Run,  # Run
                CounterBalanceNumber,  # CntrBalNum
                StimSet,  # StimSet: Which of the two stim sets are being used for this Pp?
                order,  # RuleOrder: What is the overall SoT-CoT v CoT-SoT order
                flipOrder,  # RunOrder: AB or BA, i.e. is the RuleOrder flipped for this run?
                flipOrderStr,  # The actual string of either AB or BA
                trial + 1,  # Trial number
                shape_val.name,  # Shape name
                int(Full_Trial_Array[trial, 0]),  # Shape Number
                currColNameList[int(Full_Trial_Array[trial, 1])],  # Color name
                int(Full_Trial_Array[trial, 1]),  # Color Number
                currTexList[int(Full_Trial_Array[trial, 2])],  # Texture name
                int(Full_Trial_Array[trial, 2]),  # Texture number
                currentRule,
                Full_Trial_Array[trial, 4],  # Stim Idx 
                iteration,
                buttonPressed,
                answer_keys_bBox[Full_Trial_Array[trial, 3].astype(int)],
                resp,
                Resp1Time,  #RT
                ITIs[trial],
                stimDur,
                StimOnset[trial],  # Relative to the TTL pulse (the 1st one)
                Response1_On,
                stimOffset,
                ITIOn[trial]
            ])

        trialDataArray = ','.join(trialDataArray)
        HRLDataFile.write(trialDataArray + '\n')
        os.fsync(HRLDataFile)
        HRLDataFile.flush()
        #################################################################

    #################
    ### Final ITI ###
    #################
    core.wait(ITIs[trial])  ### 133 TRs

    VALUE = str(np.round(np.divide(totalCorrect, 32) * 100, 2))
    visual.TextStim(win,
                    height=text_win_size,
                    wrapWidth=wrapWidth,
                    text='Your response accuracy was ' + VALUE + '%.' +
                    ' Press Any Key to Close').draw()
    win.flip()
    event.waitKeys()

    experimentEnd = myOverallClock.getTime()
    print("Total Experiment Time was  %s" % (experimentEnd - experimentStart))
    HRLDataFile.close()
    win.mouseVisible = True
    win.close()
    core.quit()
Example #16
0
from psychopy import visual, core, event

win = visual.Window([400, 400], allowStencil=True)
gabor1 = visual.PatchStim(win,
                          mask='circle',
                          pos=[0.3, 0.3],
                          sf=4,
                          size=1,
                          color=[0.5, -0.5, 1])
gabor2 = visual.PatchStim(win,
                          mask='circle',
                          pos=[-0.3, -0.3],
                          sf=4,
                          size=1,
                          color=[-0.5, -0.5, -1])
aperture = visual.Aperture(win, size=200, pos=[20, 0])
aperture.enable()  #actually is enabled by default when created
gabor1.draw()
aperture.disable()  #drawing from here ignores aperture
gabor2.draw()

win.flip()
event.waitKeys()
Example #17
0
                          pos=(400, 400))
triggerText = visual.TextStim(
    win=myWin,
    autoLog=False,
    color='white',
    height=30,
    text='Experiment will start soon. \n Waiting for scanner',
)
targetText = visual.TextStim(win=myWin,
                             autoLog=False,
                             color='white',
                             height=30)

vertices = [(pixCover / 2, pixCover / 2), (-pixCover / 2, pixCover / 2),
            (-pixCover / 2, -pixCover / 2), (pixCover / 2, -pixCover / 2)]
aperture = visual.Aperture(myWin, autoLog=False,
                           shape=vertices)  # try shape='square'
aperture.enabled = False

# %%
"""TIME AND TIMING PARAMETERS"""

# get screen refresh rate
refr_rate = myWin.getActualFrameRate()  # get screen refresh rate
if refr_rate is not None:
    frameDur = 1.0 / round(refr_rate)
else:
    frameDur = 1.0 / 60.0  # couldn't get a reliable measure so guess
logFile.write('RefreshRate=' + unicode(refr_rate) + '\n')
logFile.write('FrameDuration=' + unicode(frameDur) + '\n')

# set durations
Example #18
0
coords = f"screen_pixel_coords = 0 0 {SCN_W - 1} {SCN_H - 1}"
tk.sendCommand(coords)

# Request Pylink to use the custom EyeLinkCoreGraphicsPsychoPy library
# to draw calibration graphics (target, camera image, etc.)
genv = EyeLinkCoreGraphicsPsychoPy(tk, win)
pylink.openGraphicsEx(genv)

# Calibrate the tracker
calib_msg = visual.TextStim(win, text='Press ENTER to calibrate')
calib_msg.draw()
win.flip()
tk.doTrackerSetup()

# Set up a aperture and use it as a gaze-contingent window
gaze_window = visual.Aperture(win, shape='square', size=200)
gaze_window.enabled = True

# Load a background image to fill up the screen
img = visual.ImageStim(win, image='woods.jpg', size=(SCN_W, SCN_H))

# Put tracker in Offline mode before we start recording
tk.setOfflineMode()

# Start recording
tk.startRecording(1, 1, 1, 1)

# Cache some samples
pylink.msecDelay(100)

# show the image indefinitely until a key is pressed
Example #19
0
    myWin,
    width=2 * horiDist - squareSize,
    height=2 * vertiDist - squareSize,
    autoLog=False,
    name='rectStim',
    units='deg',
    fillColor=backColor,
    lineColor=backColor,
)

vertices = [(horiDist + 0.5 * squareSize, vertiDist + 0.5 * squareSize),
            (-(horiDist + 0.5 * squareSize), vertiDist + 0.5 * squareSize),
            (-(horiDist + 0.5 * squareSize), -(vertiDist + 0.5 * squareSize)),
            (horiDist + 0.5 * squareSize, -(vertiDist + 0.5 * squareSize))]

aperture = visual.Aperture(myWin, units='deg', autoLog=False, shape=vertices)
aperture.enabled = False

dotPatch = visual.ElementArrayStim(
    myWin,
    autoLog=False,
    elementTex=None,
    name='dotPatch',
    elementMask='circle',
    nElements=int(nDots),
    sizes=dotSize,
    units='deg',
    colors=dotColor,
    xys=None,
    fieldShape='square',
    fieldSize=(dimX * 2, dimY * 2),
Example #20
0
def main(win, globalClock):
    
    all_changes = []
    
    ################################ Stimuli prepation ################################

    # Bar preparation    
    grating_texture = np.tile([[1,-1],[-1,1]], (1,12))#(4,64))
    grating_texture = np.dstack((grating_texture,grating_texture,grating_texture))
    bar_size = (Bar_length[0]*resX,Bar_length[1]*resY)
    grating_1 = visual.GratingStim(win,tex=grating_texture,color=[1.0, 1.0, 1.0],colorSpace='rgb', units="pix",
        size=bar_size,ori=0,autoLog=False,interpolate=False)
    grating_2 = visual.GratingStim(win,tex=~grating_texture+1,color=[1.0, 1.0, 1.0],colorSpace='rgb', units="pix",
        size=bar_size,ori=0,autoLog=False,interpolate=False)
    
    # Vertical shifting
    bar_positions = []
    for i_ori in range(len(Bar_orientations)):
        i_x = np.linspace(Bar_paths[i_ori,0,0],Bar_paths[i_ori,1,0],Bar_positions_number).reshape((-1,1))
        i_y = np.linspace(Bar_paths[i_ori,0,1],Bar_paths[i_ori,1,1],Bar_positions_number).reshape((-1,1))
        position_i = np.concatenate((i_x,i_y), axis=1)
        position_i = position_i * resY/2
        bar_positions.append(position_i)
    
    # Fixation cross preparation
    fixation = visual.ShapeStim(win,vertices=((0,-1),(0,1),(0,0),(-1,0),(1,0)),lineWidth=4, units="pix",
        size=(20,20),closeShape=False,lineColor='red',autoDraw=True)
    
    # Spyder network
    web_circle = visual.Circle(win=win,radius=1,edges=200,units='norm',pos=[0, 0],lineWidth=1,opacity=1,interpolate=True,
                            lineColor=[1.0, 1.0, 1.0],lineColorSpace='rgb',fillColor=None,fillColorSpace='rgb')
    web_dimension = (screenCorrection(win,Web_size[0]),Web_size[1])
    web_line = visual.Line(win,name='Line',start=(-1.4, 0),end=(1.4, 0),pos=[0, 0],lineWidth=1,
                           lineColor=[1.0, 1.0, 1.0],lineColorSpace='rgb',opacity=1,interpolate=True)

    # DEBUG stimuli
    if DEBUG_MODE:
        fps_text = visual.TextStim(win, units='norm', height=0.05,pos=(-0.98, +0.93), text='starting...',
                                  font=sans, alignHoriz='left', alignVert='bottom', color='yellow')    
        fps_text.autoDraw = True
        
        orientation_details_string = visual.TextStim(win, text = u"Orientation..", units='norm', height=0.05,
                                             pos=(0.95, +0.93), alignHoriz='right', alignVert='bottom', 
                                             font=sans, color='yellow')
        orientation_details_string.autoDraw = True        

    # External Aperture (black ring)
    external_aperture_size = tuple([screenCorrection(win,External_ring_size),External_ring_size])
    external_aperture = visual.Aperture(win, size=external_aperture_size, shape='circle')
    external_aperture.enabled = False

    ################################ Definitions/Functions ################################    
    
    ## handle Rkey presses each frame
    def escapeCondition():              
        for key in event.getKeys():
            if key in ['escape', 'q']:
                return False
        return True
    

    ################################ Animation starts ################################        
    # Display instructions and wait
    message1 = visual.TextStim(win, pos=[0,0.5],text='Hit a key when ready.')
    message1.draw()
    win.flip()
    event.waitKeys()    #pause until there's a keypress

    # Scanner trigger wait
    message3 = visual.TextStim(win,pos=[0,0.25],text=scanner_message,font=serif,alignVert='center',
                               wrapWidth=1.5)
    message3.size = .5
    message3.draw()
    win.flip()

    if BUTTON_BOX:
        button_state = button_thread.button_state
        while 1:
            if(button_state['state'][-1]==0):
                break
    else:
        event.waitKeys()    #pause until there's a keypress
  
    
    # Wait Pre_post_stimuli_fixation_time before stimuli
    # Spyder network
    if Spyder_grid:
        for i_dim in range(Spyder_rings):
            web_circle.setSize(tuple([x*(i_dim+1) * 1./Spyder_rings for x in web_dimension]))
            web_circle.draw()
        for i_dim in range(2):
            web_line.setOri(i_dim * 90)
            web_line.draw()
    win.flip()
    core.wait(Pre_post_stimuli_fixation_time)
    
    
    i_bar_ori = n_frame = last_fps_update = 0

    globalClock.reset()
    inizio = globalClock.getTime()
    timer_global = core.CountdownTimer(Total_time)    
    break_flag = True
    logging.data('First orientation. Number %d/%d at %f (sec.)' % (i_bar_ori+1,len(Bar_orientations),inizio))
    
    
    while (timer_global.getTime() > 0 and break_flag==True):                      #globalClock.getTime() < Total_time:
        n_frame += 1
        t = globalClock.getTime()

        # Spyder network
        if Spyder_grid:
            for i_dim in range(Spyder_rings):
                web_circle.setSize(tuple([x*(i_dim+1) * 1./Spyder_rings for x in web_dimension]))
                web_circle.draw()
            for i_dim in range(2):
                web_line.setOri(i_dim * 90)
                web_line.draw()

        # External ring
        external_aperture.enabled = True
                
        # Bar
        if (t >= ((i_bar_ori+1)*Cycle_duration*Passagges_per_orientation)) & (i_bar_ori < (len(Bar_orientations)-1)):
            i_bar_ori += 1
            logging.data('Change orientation. Number %d/%d at %f (sec.)' % (i_bar_ori+1,len(Bar_orientations),t))
            new_record = globalClock.getTime() - sum(all_changes)
            all_changes.append(new_record)        
        
        if t % Flash_period < Flash_period / 2.0:  # more accurate to count frames
            stim = grating_1
        else:
            stim = grating_2
        bar_pos_indx = int((Bar_positions_number / Cycle_duration) * (t % Cycle_duration) )
        i_orientation_ordered = Bar_orientation_order[i_bar_ori]
        stim.pos = tuple(bar_positions[i_orientation_ordered][bar_pos_indx])
        stim.ori = Bar_orientations[i_orientation_ordered]
        stim.draw()
        
                
        # Fixation
        if Rotating_cross:
            fixation.ori = t * Rotation_cross_rate * 360.0  # set new rotation
        if Color_change_cross:
            if t % Color_change_rate < Color_change_rate / 2.0:  # more accurate to count frames
                fixation.lineColor = 'red'
            else:
                fixation.lineColor = 'green'        

        external_aperture.enabled = False
        if DEBUG_MODE:
            if t - last_fps_update > Fps_update_rate:         # update the fps text every second
                fps_text.text = "%.2f fps" % win.fps()
                last_fps_update += 1
            orientation_details_string.text = 'Ori: %d/%d at %.3f (sec.)' % (i_bar_ori+1,len(Bar_orientations),np.sum(all_changes))

        # Update screen                
        win.flip()
        break_flag = escapeCondition()
        if break_flag == False: break
    

    logging.data('Total time spent: %.6f' % (globalClock.getTime() - inizio))
    logging.data('Every frame duration saved in %s' % (path_out+Frames_durations_name))
    logging.data('All durations: ' + str(all_changes))
    logging.data('Mean: ' + str(sum(all_changes)/(len(all_changes)+EPSILON)))

    if DEBUG_MODE:
        orientation_details_string.text = 'Ended at %.3f (sec.)' % (globalClock.getTime())

    win.flip()
    # Wait Pre_post_stimuli_fixation_time after stimuli
    core.wait(Pre_post_stimuli_fixation_time)
    return
Example #21
0
                                mask='raisedCos',
                                color=0,
                                size=1)

message = visual.TextStim(win,
                          text='Press q to quit',
                          pos=(-0.95, -0.95),
                          units='norm',
                          anchorVert='bottom',
                          anchorHoriz='left')

trialClock = core.Clock()
t = 0

# create aperture from mask
aperture = visual.Aperture(win, size=.5,
                           shape=mask.verticesPix)  # try shape='square'

for x in range(nTrials):
    trialClock.reset()
    t = 0
    while t < 10:  # quits after 20 secs
        t = trialClock.getTime()
        # set grating contrast
        grating1.contrast = sin(t * pi * 4)
        grating2.contrast = sin(t * pi * 4)

        # initally draw right side
        aperture.ori = 0
        aperture.enabled = True  # enabled by default when created
        # draw plaid
        grating1.draw()
def main(win, globalClock):

    all_changes_ecc = []
    all_changes_pol = []
    size_ecc_pxl = resY * Eccentricity_size

    ################################ Stimuli prepation ################################

    # Make two wedges (in opposite contrast) and alternate them for flashing
    grating_texture = np.tile([[1, -1], [-1, 1]], (8, 8))  #(4,64))
    wedge1 = visual.RadialStim(win,
                               tex=grating_texture,
                               color=1,
                               units='pix',
                               size=size_ecc_pxl,
                               radialCycles=1,
                               angularCycles=2,
                               interpolate=False,
                               autoLog=False)  #, mask=radius)
    wedge2 = copy.copy(wedge1)
    wedge2.color = -1

    position_from_center = np.linspace(0, size_ecc_pxl,
                                       Mask_positions_number).reshape((-1, 1))

    # Make two wedges (in opposite contrast) and alternate them for flashing
    polar1 = visual.RadialStim(
        win,
        tex=grating_texture,
        color=1,
        units='pix',
        size=win.size[1] * 1.3,
        visibleWedge=[Initial_wedge_pos, Initial_wedge_pos + Wedge_width],
        interpolate=False,
        autoLog=False,
        radialCycles=1,
        angularCycles=4)
    polar2 = copy.copy(polar1)
    polar2.color = -1

    # fixation cross
    fixation = visual.ShapeStim(win,
                                vertices=((0, -1), (0, 1), (0, 0), (-1, 0),
                                          (1, 0)),
                                lineWidth=4,
                                units="pix",
                                size=(20, 20),
                                closeShape=False,
                                lineColor='red',
                                autoDraw=True)

    # Spyder network
    web_circle = visual.Circle(win=win,
                               radius=1,
                               edges=200,
                               units='norm',
                               pos=[0, 0],
                               lineWidth=1,
                               opacity=1,
                               interpolate=True,
                               lineColor=[1.0, 1.0, 1.0],
                               lineColorSpace='rgb',
                               fillColor=None,
                               fillColorSpace='rgb')
    web_dimension = (screenCorrection(win, Web_size[0]), Web_size[1])
    web_line = visual.Line(win,
                           name='Line',
                           start=(-1.4, 0),
                           end=(1.4, 0),
                           pos=[0, 0],
                           lineWidth=1,
                           lineColor=[1.0, 1.0, 1.0],
                           lineColorSpace='rgb',
                           opacity=1,
                           interpolate=True)

    # DEBUG stimuli
    if DEBUG_MODE:
        fps_text = visual.TextStim(win,
                                   units='norm',
                                   height=0.05,
                                   pos=(-0.98, +0.93),
                                   text='starting...',
                                   font=sans,
                                   alignHoriz='left',
                                   alignVert='bottom',
                                   color='yellow')
        fps_text.autoDraw = True

        orientation_details_string = visual.TextStim(win,
                                                     text=u"eccentricity..",
                                                     units='norm',
                                                     height=0.05,
                                                     pos=(0.95, +0.93),
                                                     alignHoriz='right',
                                                     alignVert='bottom',
                                                     font=sans,
                                                     color='yellow')
        orientation_details_string.autoDraw = True

    # External Aperture (black ring)
    external_aperture_size = tuple(
        [screenCorrection(win, External_ring_size), External_ring_size])
    external_aperture = visual.Aperture(win,
                                        size=external_aperture_size,
                                        shape='circle')
    external_aperture.enabled = False

    ################################ Definitions/Functions ################################

    ## handle Rkey presses each frame
    def escapeCondition():
        for key in event.getKeys():
            if key in ['escape', 'q']:
                return False
        return True

    ################################ Animation starts ################################
    # display instructions and wait
    message1 = visual.TextStim(win, pos=[0, 0.5], text='Hit a key when ready.')
    message1.draw()
    fixation.draw()
    win.flip()  #to show our newly drawn 'stimuli'
    event.waitKeys()  #pause until there's a keypress

    # Scanner trigger wait
    message3 = visual.TextStim(win,
                               pos=[0, 0.25],
                               text=scanner_message,
                               font=serif,
                               alignVert='center',
                               wrapWidth=1.5)
    message3.size = .5
    message3.draw()
    win.flip()

    if BUTTON_BOX:
        button_state = button_thread.button_state
        while 1:
            if (button_state['state'][-1] == 0):
                break
    else:
        event.waitKeys()  #pause until there's a keypress

    # Wait Pre_post_stimuli_fixation_time before stimuli
    # Spyder network
    if Spyder_grid:
        for i_dim in range(Spyder_rings):
            web_circle.setSize(
                tuple([
                    x * (i_dim + 1) * 1. / Spyder_rings for x in web_dimension
                ]))
            web_circle.draw()
        for i_dim in range(2):
            web_line.setOri(i_dim * 90)
            web_line.draw()
    win.flip()
    core.wait(Pre_post_stimuli_fixation_time)

    t = last_fps_update = i_cycle_ecc = i_cycle_pol = new_record_ecc = new_record_pol = 0
    break_flag = True
    globalClock.reset()
    inizio = globalClock.getTime()
    logging.data('First cycle Eccentricity. Number %d/%d at %f (sec.)' %
                 (i_cycle_ecc + 1, Cycles_number_ecc, inizio))
    logging.data('First cycle Polar. Number %d/%d at %f (sec.)' %
                 (i_cycle_pol + 1, Cycles_number_polar, inizio))

    while (globalClock.getTime() < Total_time and break_flag == True):
        t = globalClock.getTime()

        # Spyder network
        if Spyder_grid:
            for i_dim in range(Spyder_rings):
                web_circle.setSize(
                    tuple([
                        x * (i_dim + 1) * 1. / Spyder_rings
                        for x in web_dimension
                    ]))
                web_circle.draw()
            for i_dim in range(2):
                web_line.setOri(i_dim * 90)
                web_line.draw()

        # External ring
        external_aperture.enabled = True

        if t % Flash_period < Flash_period / 2.0:  # more accurate to count frames
            wedge = wedge1
            polar = polar1
        else:
            wedge = wedge2
            polar = polar2

        polar.ori = -t * Rotation_rate * 360.0  # set new rotation

        # Prepare moving mask
        if (t >= ((i_cycle_ecc + 1) * Cycle_duration_ecc)):
            logging.data(
                'Change orientation (eccentricity). Number %d/%d at %f (sec.)'
                % (i_cycle_ecc + 1, Cycles_number_ecc, t))
            new_record_ecc = globalClock.getTime() - sum(all_changes_ecc)
            all_changes_ecc.append(new_record_ecc)

        if (t >= ((i_cycle_pol + 1) * Cycle_duration_polar)):
            logging.data(
                'Change orientation (polar). Number %d/%d at %f (sec.)' %
                (i_cycle_pol + 1, Cycles_number_polar, t))
            new_record_pol = globalClock.getTime() - sum(all_changes_pol)
            all_changes_pol.append(new_record_pol)

        i_cycle_ecc = int(t / Cycle_duration_ecc)
        i_cycle_pol = int(t / Cycle_duration_polar)
        crown_pos_indx = int((Mask_positions_number / Cycle_duration_ecc / 2) *
                             (t % Cycle_duration_ecc))
        ## Try to understand when it changes and save it
        mask_begin = int(position_from_center[crown_pos_indx, 0])
        mask_end = int(position_from_center[crown_pos_indx, 0] +
                       Thickness_multiplication_factor[crown_pos_indx] *
                       Thickness_circular_crown)

        annulus_mask = np.zeros((int(size_ecc_pxl / 2), 1))
        annulus_mask[
            mask_begin:
            mask_end] += 1  #int(mask_end if mask_end <= size_ecc_pxl else size_ecc_pxl)] += 1
        wedge.setMask(annulus_mask)
        wedge.draw()
        polar.draw()

        # Fixation
        if Rotating_cross:
            fixation.ori = t * Rotation_cross_rate * 360.0  # set new rotation
        if Color_change_cross:
            if t % Color_change_rate < Color_change_rate / 2.0:  # more accurate to count frames
                fixation.lineColor = 'red'
            else:
                fixation.lineColor = 'green'

        external_aperture.enabled = False

        if DEBUG_MODE:
            if t - last_fps_update > Fps_update_rate:  # update the fps text every second
                fps_text.text = "%.2f fps" % win.fps()
                last_fps_update += 1


#            orientation_details_string.text = 'Pass: %d/%d at %.3f (sec.)' % (i_cycle+1,Cycles_number,np.sum(all_changes))

        win.flip()
        break_flag = escapeCondition()
        if break_flag == False: break

    logging.data('Total time planned: %.6f' % (Total_time))
    logging.data('Total time spent: %.6f' % (globalClock.getTime() - inizio))
    logging.data('Every frame duration saved in %s' %
                 (path_out + Frames_durations_name))
    logging.data('All durations Eccentricity: ' + str(all_changes_ecc))
    logging.data('All durations Polar: ' + str(all_changes_pol))
    logging.data('Mean Eccentricity: ' +
                 str(sum(all_changes_ecc) / (len(all_changes_ecc) + EPSILON)))
    logging.data('Mean Polar: ' +
                 str(sum(all_changes_pol) / (len(all_changes_pol) + EPSILON)))

    if DEBUG_MODE:
        orientation_details_string.text = 'Ended at %.3f (sec.)' % (
            globalClock.getTime())

    win.flip()
    # Wait Pre_post_stimuli_fixation_time after stimuli
    core.wait(Pre_post_stimuli_fixation_time)
    return
    berry3.opacity = 1

    #getting the location of mouse
    mouse_location = default_mouse.getPos()

    #drawing the elements to be drawn permanently aka every frame
    grass.setAutoDraw(True)

    berry1.setAutoDraw(True)
    berry2.setAutoDraw(True)
    berry3.setAutoDraw(True)

    #aperture is drawn every frame and aperture gets to position of mouse foe the 'spotlight' like movemnet to happen
    aperture = visual.Aperture(win,
                               name='aperture',
                               shape='circle',
                               units='pix',
                               size=100,
                               pos=default_mouse.getPos())

    #setting the position where the reward and time elapsed will be displayed
    text.pos = [-580, 300]
    time_text.pos = [580, 300]
    reward_text.pos = default_mouse.getPos()

    #changing the texts on every update
    time_elapsed = clock.getAbsTime() - start_time
    time_text.text = 'Time elapsed:' + str(clock.getAbsTime() - start_time)
    text.text = 'Total reward:' + str(np.sum(collected))

    #making the berry images a clickable stimuli
    berry1_click = default_mouse.isPressedIn(berry1, buttons=[0])
Example #24
0
# Filename: demo_aperture.py

from psychopy import visual, core, event

# create a window
win = visual.Window(size=(800, 600),
                    units="pix",
                    fullscr=False,
                    color=[0, 0, 0],
                    allowStencil=True)

# create an aperture
#apt = visual.Aperture(win, size=300, shape='circle', inverted=True)
vert = [(0.1, .50), (.45, .20), (.10, -.5), (-.60, -.5), (-.5, .20)]
apt = visual.Aperture(win, size=200, shape=vert, inverted=True)
apt.enabled = True

#create a mouse instance
mouse = event.Mouse(visible=False)

# prepare the stimuli
text = visual.TextStim(win,
                       text="Moving window example by Zhiguo" * 24,
                       height=30,
                       color='black',
                       wrapWidth=760)

# mouse-contingent moving window
while not event.getKeys():
    apt.pos = mouse.getPos()
    text.draw()
Example #25
0
# make a monitor with monitor constants from the init file
mon = expsetup.makeMonitor(init['monitor_constants'])
# and make a window using that monitor
win = visual.Window(
    monitor=mon,
    color=init['experiment']['bkgcolor'],
    size=mon.getSizePix(),
    units='deg',
    screen=1,  # 0 is the monitor of the experiment control
    fullscr=True,
    allowGUI=False,
    waitBlanking=False,
    allowStencil=True,
    winType='pyglet')  # for iohub to function well

aperture = visual.Aperture(win, size=20)
aperture.units = 'deg'

# velocity is upward, computed from the oblique velocity vector
# this velocity is in periods/s
# the velocity is thus relatif to the vertical period which is 1/(sin(theta)*sf) [deg]
vel_ori = -90

sf_x = stims.get_angular_frequency(0, stim_params['sf'], stim_params['ori'])
sf_y = stims.get_angular_frequency(90, stim_params['sf'], stim_params['ori'])
v_y = stims.get_angular_velocity(90, stim_params['vel'], stim_params['ori'])
velocity = lambda vel_ori: np.array([
    v_y * sf_x * np.cos(stims._deg2rad(vel_ori)), v_y * sf_y * np.sin(
        stims._deg2rad(vel_ori))
])
    size=(1024, 768), fullscr=True, screen=0, 
    winType='pyglet', allowGUI=False, allowStencil=True,
    monitor='testMonitor', color=[0,0,0], colorSpace='rgb',
    blendMode='avg', useFBO=True, 
    units='height')
# store frame rate of monitor if we can measure it
expInfo['frameRate'] = win.getActualFrameRate()
if expInfo['frameRate'] != None:
    frameDur = 1.0 / round(expInfo['frameRate'])
else:
    frameDur = 1.0 / 60.0  # could not measure, so guess

# Initialize components for Routine "trial"
trialClock = core.Clock()
aperture = visual.Aperture(
    win=win, name='aperture',
    units='norm', size=1, pos=(0, 0))
aperture.disable()  # disable until its actually used

# Create some handy timers
globalClock = core.Clock()  # to track the time since experiment started
routineTimer = core.CountdownTimer()  # to track time remaining of each (non-slip) routine 

# ------Prepare to start Routine "trial"-------
t = 0
trialClock.reset()  # clock
frameN = -1
continueRoutine = True
routineTimer.add(1.000000)
# update component parameters for each repeat
# keep track of which components have finished
Example #27
0
def prf_stim(dicParam):
    """
    Present stimuli for population receptive field mapping.

    If in logging mode, this script creates a stimulus log of the stimuli used
    for the pRF mapping that can be used for the pRF finding analysis of the
    pyprf library. The stimuli are saved as png files, where each png
    represents the status of visual stimulation for one TR (the png files
    contain modified screenshots of the visual stimulus, and can be directly be
    loaded into the py_pRF_mapping pipepline.
    """
    # *****************************************************************************
    # *** Experimental parameters (from dictionary)

    # Path of design matrix (npz):
    strPthNpz = dicParam['Path of design matrix (npz)']

    # Output path & file name of log file:
    strPthLog = dicParam['Output path (log files)']

    # Target duration [s]:
    varTrgtDur = float(dicParam['Target duration [s]'])

    # Logging mode (logging mode is for creating files for analysis, not to be
    # used during an experiment).
    lgcLogMde = dicParam['Logging mode']

    # On windows, the return value may be a string, not a bool. We need to
    # correct for this.
    if not (isinstance(lgcLogMde, bool)):
        if lgcLogMde == 'True':
            lgcLogMde = True
        else:
            lgcLogMde = False

    # Directory where to save stimulus log (frames) for analysis if in logging
    # mode.
    strPthFrm = dicParam['Output path stimulus log (frames)']

    # Frequency of stimulus bar in Hz:
    varGrtFrq = float(dicParam['Temporal frequency [Hz]'])

    # Sptial frequency of stimulus (cycles along width of bar stimulus):
    varBarSf = float(dicParam['Spatial frequency [cyc per bar]'])

    # Distance between observer and monitor [cm]:
    varMonDist = float(dicParam['Distance between observer and monitor [cm]'])

    # Width of monitor [cm]:
    varMonWdth = float(dicParam['Width of monitor [cm]'])

    # Width of monitor [pixels]:
    varPixX = int(dicParam['Width of monitor [pixels]'])

    # Height of monitor [pixels]:
    varPixY = int(dicParam['Height of monitor [pixels]'])

    # Background colour:
    varBckgrd = float(dicParam['Background colour [-1 to 1]'])

    # Show fixation grid?
    lgcGrd = dicParam['Show fixation grid?']

    # On windows, the return value may be a string, not a bool. We need to
    # correct for this.
    if not (isinstance(lgcGrd, bool)):
        if lgcGrd == 'True':
            lgcGrd = True
        else:
            lgcGrd = False

    # *************************************************************************
    # *** Retrieve design matrix

    # Load stimulus parameters from npz file.
    objNpz = np.load(strPthNpz)

    # Get design matrix (for bar positions and orientation):
    aryDsg = objNpz['aryDsg']

    # Number of volumes:
    varNumVol = aryDsg.shape[0]

    # Vector with times of target events:
    vecTrgt = objNpz['vecTrgt']

    # Number of target events:
    varNumTrgt = vecTrgt.shape[0]

    # Full screen mode? If no, bar stimuli are restricted to a central square.
    # If yes, bars appear on the entire screen. This parameter is set when
    # creating the design matrix.
    lgcFull = bool(objNpz['lgcFull'])

    # Number of bar positions on x-axis:
    varNumPosX = int(objNpz['varNumPosX'])

    # Number of bar positions on y-axis:
    varNumPosY = int(objNpz['varNumPosY'])

    # If in full screen mode, we need to make sure that the bar position along
    # the shorted axis (x-axis) is adjusted, so that the bar is always within
    # the screen area (and not half cut off).
    if lgcFull:
        # Ratio of bar positions (from design matrix), e.g. 18/11:
        varRatioPos = float(varNumPosX) / float(varNumPosY)
        # Ratio of screen widht/height in pixels (e.g. 1920/1200):
        varRatioPix = float(varPixX) / float(varPixY)
        # Scaling factor for bar positions along x-axis:
        varSclPosX = varRatioPos / varRatioPix

    # Adjustments for logging mode:
    if lgcLogMde:

        # Conditional imports:
        from PIL import Image
        from scipy.stats import mode

        # If in logging mode, only present stimuli very briefly. Note: If
        # 'varTr' is set too low in logging mode, frames are dropped and the
        # stimuli do not get logged properly.
        varTr = 0.2

        # In log mode, don't show grid.
        lgcGrd = False

    # Otherwise, use actual volume TR:
    else:
        # Volume TR:
        varTr = float(objNpz['varTr'])

    # *************************************************************************
    # *** Logging

    # Set clock:
    objClck = core.Clock()

    # Set clock for logging:
    logging.setDefaultClock(objClck)

    # Create a log file and set logging verbosity:
    fleLog = logging.LogFile(strPthLog, level=logging.DATA)

    # Log stimulus parameters:
    fleLog.write('Log file path: ' + strPthLog + '\n')
    fleLog.write('Design matrix: ' + strPthNpz + '\n')
    fleLog.write('Full screen: ' + str(lgcFull) + '\n')
    fleLog.write('Volume TR [s] (from design matrix): ' + str(varTr) + '\n')
    fleLog.write('Frequency of stimulus bar in Hz: ' + str(varGrtFrq) + '\n')
    fleLog.write('Sptial frequency of stimulus (cycles along width of ' +
                 'bar stimulus): ' + str(varBarSf) + '\n')
    fleLog.write('Distance between observer and monitor [cm]: ' +
                 str(varMonDist) + '\n')
    fleLog.write('Width of monitor [cm]: ' + str(varMonWdth) + '\n')
    fleLog.write('Width of monitor [pixels]: ' + str(varPixX) + '\n')
    fleLog.write('Height of monitor [pixels]: ' + str(varPixY) + '\n')
    fleLog.write('Background colour [-1 to 1]: ' + str(varBckgrd) + '\n')
    fleLog.write('Target duration [s]: ' + str(varTrgtDur) + '\n')
    fleLog.write('Logging mode: ' + str(lgcLogMde) + '\n')

    # Set console logging verbosity:
    logging.console.setLevel(logging.WARNING)

    # *************************************************************************
    # *** Prepare behavioural response logging

    # Switch target (show target or not?):
    varSwtTrgt = 0

    # Control the logging of participant responses:
    varSwtRspLog = 0

    # The key that the participant has to press after a target event:
    strTrgtKey = '1'

    # Counter for correct/incorrect responses:
    varCntHit = 0  # Counter for hits
    varCntMis = 0  # Counter for misses

    # Time (in seconds) that participants have to respond to a target event in
    # order for the event to be logged as a hit:
    varHitTme = 2.0

    # *************************************************************************
    # *** Setup

    # Create monitor object:
    objMon = monitors.Monitor('Screen_7T_NOVA_32_Channel_Coil',
                              width=varMonWdth,
                              distance=varMonDist)

    # Set size of monitor:
    objMon.setSizePix([varPixX, varPixY])

    # Set screen:
    objWin = visual.Window(
        size=(varPixX, varPixY),
        screen=0,
        winType='pyglet',  # winType : None, 'pyglet', 'pygame'
        allowGUI=False,
        allowStencil=True,
        fullscr=True,
        monitor=objMon,
        color=varBckgrd,
        colorSpace='rgb',
        units='deg',
        blendMode='avg')

    # *************************************************************************
    # *** Spatial stimulus properties

    # The area that will be covered by the bar stimulus depends on whether
    # presenting in full screen mode or not. If in full screen mode, the
    # entire width of the screen will be covered. If not, a central square
    # with a side length equal to the screen height will be covered.
    if lgcFull:
        varPixCov = varPixX
    else:
        varPixCov = varPixY

    # Convert size in pixels to size in degrees (given the monitor settings):
    # varDegCover = pix2deg(varPixCov, objMon)

    # Numberic codes used for bar positions:
    vecPosCode = np.unique(aryDsg[:, 1])

    # Number of bar positions:
    varNumPos = vecPosCode.shape[0]

    # The thickness of the bar stimulus depends on the size of the screen to
    # be covered, and on the number of positions at which to present the bar.
    # Bar thickness in pixels:
    varThckPix = float(varPixCov) / float(varNumPos)

    # Bar thickness in degree:
    varThckDgr = np.around(pix2deg(varThckPix, objMon), decimals=5)

    # Write stimulus parameters to log file.
    fleLog.write('* * * Stimulus properties in degrees of visual angle ' +
                 '* * * \n')
    fleLog.write('Width of bar stimulus [deg]: ' + str(varThckDgr) + '\n')

    # Spatial frequency of bar stimulus is defined (in user input) as cycles
    # along width of the bar  stimulus. We need to convert this to cycles per
    # pixel (for the stimulus creation) and to cycles per degree (for
    # reference, written to log file).

    # Spatial frequency in cycles per pixel:
    varBarSfPix = float(varBarSf) / varThckPix
    tplBarSfPix = (varBarSfPix, varBarSfPix)

    # Spatial frequency in cycles per degree of visual angle (for reference
    # only):
    varBarSfDeg = np.around((float(varBarSf) / varThckDgr), decimals=5)

    # Write stimulus parameters to log file.
    fleLog.write('Spatial frequency of bar stimulus [cyc/deg]: ' +
                 str(varBarSfDeg) + '\n')
    fleLog.write('* * * \n')

    # Bar stimulus size (length & thickness), in pixels.
    tplBarSzePix = (varPixX, int(varThckPix))

    # Offset of the bar stimuli. The bar stimuli should cover the screen area,
    # without extending beyond the screen. Because their position refers to
    # the centre of the bar, we need to limit the extend of positions at the
    # edge of the screen by an offset, Offset in pixels:
    varOffsetPix = varThckPix * 0.5

    # Maximum bar position in pixels, with respect to origin at centre of
    # screen:
    varPosMaxPix = (float(varPixCov) * 0.5) - float(varOffsetPix)

    # Array of possible bar positions (displacement relative to origin at
    # centre of the screen) in pixels:
    vecPosPix = np.linspace(-varPosMaxPix,
                            varPosMaxPix,
                            varNumPos,
                            endpoint=True)

    # Replace numeric position codes with pixel position values:
    for idxPos, varPos in enumerate(vecPosCode):

        # Replace current position code, if this is not a rest block:
        vecLgc = np.multiply((aryDsg[:, 1] == varPos), (aryDsg[:, 0] != 0.0))

        # Place pixel position value in design matrix:
        aryDsg[vecLgc, 1] = vecPosPix[idxPos]

    # Psychopy orientation convention: "Orientation convention is like a clock:
    # 0 is vertical, and positive values rotate clockwise." Actually, 0 is the
    # positive x-axis. Orientations are coded as follows: horizontal = 0.0,
    # vertical = 90.0, lower left to upper right = 45.0, upper left to lower
    # right = 135.0. We need to convert psychopy orientation & direction
    # convention into x and y coordinates.
    lstPos = [None] * varNumVol
    for idxVol in range(varNumVol):

        # Get angle and radius of current volume:
        varRad = float(aryDsg[idxVol, 1])
        varAngle = float(aryDsg[idxVol, 2])

        # Horizontal:
        if varAngle == 0.0:
            varTmpX = 0.0

            # If in full screen mode, make sure that the bar is not partially
            # outside of the screen area.
            if lgcFull:
                # Scale y-position.
                varTmpY = varRad * varSclPosX
            else:
                # Not in full screen mode, don't scale.
                varTmpY = varRad

        # Vertical:
        elif varAngle == 90.0:
            varTmpX = varRad
            varTmpY = 0.0

        # Lower left to upper right:
        elif varAngle == 45.0:
            if varRad < 0.0:
                varTmpX = -np.sqrt(np.add(np.square(varRad),
                                          np.square(varRad)))
            elif 0.0 < varRad:
                varTmpX = np.sqrt(np.add(np.square(varRad), np.square(varRad)))
            else:
                varTmpX = 0.0
            varTmpY = 0.0

        # Upper left to lower right:
        elif varAngle == 135.0:
            if varRad < 0.0:
                varTmpX = -np.sqrt(np.add(np.square(varRad),
                                          np.square(varRad)))
            elif 0.0 < varRad:
                varTmpX = np.sqrt(np.add(np.square(varRad), np.square(varRad)))
            else:
                varTmpX = 0.0
            varTmpY = 0.0

        # Position is coded as a tuple:
        lstPos[idxVol] = (varTmpX, varTmpY)

    # *************************************************************************
    # *** Stimuli

    # Bar stimulus:
    objBar = visual.GratingStim(objWin,
                                contrast=1.0,
                                pos=(0.0, 0.0),
                                tex='sqrXsqr',
                                color=[1.0, 1.0, 1.0],
                                colorSpace='rgb',
                                opacity=1.0,
                                size=tplBarSzePix,
                                sf=tplBarSfPix,
                                ori=0.0,
                                autoLog=False,
                                interpolate=False,
                                units='pix')

    # Colour of fixation dot:
    lstClrFix = [-0.69, 0.83, 0.63]
    # lstClrFix = [0.04, 0.95, -1.0]

    # Colour of fixation dot when it becomes a target:
    lstClrTrgt = [0.95, 0.04, -1.0]

    # Fixation dot:
    objFix = visual.Circle(objWin,
                           units='deg',
                           pos=(0.0, 0.0),
                           radius=0.05,
                           edges=24,
                           fillColor=lstClrFix,
                           fillColorSpace='rgb',
                           lineColor=lstClrFix,
                           lineColorSpace='rgb',
                           lineWidth=0.0,
                           interpolate=False,
                           autoLog=False)

    # Fication dot surround:
    objFixSrd = visual.Circle(objWin,
                              units='deg',
                              pos=(0.0, 0.0),
                              radius=0.09,
                              edges=24,
                              fillColor=lstClrTrgt,
                              fillColorSpace='rgb',
                              lineColor=lstClrTrgt,
                              lineColorSpace='rgb',
                              lineWidth=0.0,
                              interpolate=False,
                              autoLog=False)

    if lgcGrd:

        # Number of grid circles:
        varNumCrcl = 3

        # Radi at which to present grid circles:
        vecGrdCrclRad = np.linspace((0.25 * float(varPixY)),
                                    (0.75 * float(varPixY)),
                                    num=varNumCrcl)

        # In practice 'radius' seems to refer to refer to the diameter of the
        # circle.

        # Fixation grid circles:
        lstGrdCrcl = [None] * varNumCrcl
        for idxCrcl, varRad in enumerate(vecGrdCrclRad):
            lstGrdCrcl[idxCrcl] = visual.Circle(win=objWin,
                                                pos=(0.0, 0.0),
                                                radius=varRad,
                                                edges=128,
                                                lineWidth=1.0,
                                                lineColor=[-0.8, -0.8, -0.8],
                                                lineColorSpace='rgb',
                                                fillColor=None,
                                                fillColorSpace='rgb',
                                                opacity=1.0,
                                                autoLog=False,
                                                interpolate=True,
                                                units='pix')

        # Fixation grid line:
        lstGrdLne = [None] * 4
        for idxLne, varOri in enumerate([0.0, 45.0, 90.0, 135.0]):
            lstGrdLne[idxLne] = visual.Line(win=objWin,
                                            ori=varOri,
                                            start=(int(-varPixY), 0),
                                            end=(int(varPixY), 0),
                                            pos=(0.0, 0.0),
                                            lineWidth=1.0,
                                            lineColor=[-0.8, -0.8, -0.8],
                                            lineColorSpace='rgb',
                                            fillColor=None,
                                            fillColorSpace='rgb',
                                            opacity=1.0,
                                            autoLog=False,
                                            interpolate=True,
                                            units='pix')

    # *************************************************************************
    # *** Aperture

    # The area that will be covered by the bar stimulus depends on whether
    # presenting in full screen mode or not. If in full screen mode, the entire
    # width of the screen will be covered. If not, a central square with a side
    # length equal to the screen height will be covered.

    if not (lgcFull):

        # Aperture side length in degree. For some reason, the aperture does
        # not seem to accept pixel units.
        varDegCov = pix2deg(float(varPixCov), objMon)

        # Aperture for covering left and right side of screen if not presenting
        # in full screen mode.
        objAprtr = visual.Aperture(objWin,
                                   size=varDegCov,
                                   pos=(0, 0),
                                   shape='square',
                                   inverted=False,
                                   units='deg')

        objAprtr.enabled = True

    # *************************************************************************
    # *** Logging mode preparations

    if lgcLogMde:

        print('Logging mode')

        # Calculate area to crop in x-dimension, at left and right (zero is
        # full extend of screeen width is used):
        if lgcFull:
            varCrpX = 0
        else:
            varCrpX = int(np.around((float(varPixX) - float(varPixY)) * 0.5))

        print(('Stimulus log will be cropped by ' + str(varCrpX) +
               ' in x-direction (screen width).'))

        # Temporary array for screenshots, at full screen size and containing
        # RGB values (needed to obtain buffer content from psychopy):
        aryBuff = np.zeros((varPixY, varPixX, 3), dtype=np.int8)

        # It is not necessary to sample every pixel; only every second pixel is
        # sampled. Number of pixel to be sampled along x and y direction:
        varHalfPixX = int(np.around(varPixX * 0.5))
        varHalfPixY = int(np.around(varPixY * 0.5))

        # Prepare array for screenshots. One value per pixel per volume; since
        # the stimuli are greyscale we discard 2nd and 3rd RGB dimension. Also,
        # there is no need to represent the entire screen, just the part of the
        # screen that is actually stimulated (if not in full screen mode, this
        # is a square at the centre of the screen, flanked by unstimulated
        # areas on the left and right side).
        if lgcFull:
            aryFrames = np.zeros((varHalfPixY, varHalfPixX, varNumVol),
                                 dtype=np.uint8)
        else:
            aryFrames = np.zeros((varHalfPixY, varHalfPixY, varNumVol),
                                 dtype=np.uint8)

        # Counter for screenshots:
        idxFrame = 0

    # *************************************************************************
    # *** Timing & switches

    # Target counter:
    varCntTrgt = 0

    # Time of the first target event:
    varTmeTrgt = vecTrgt[varCntTrgt]

    # Switch for grating polarity flicker:
    varSwtGrt = 0

    # The input parameter 'varGrtFrq' gives the grating flicker frequency in
    # Hz. We need to convert to second:
    varGrtDur = 1.0 / float(varGrtFrq)

    # *************************************************************************
    # *** Presentation

    # Hide the mouse cursor:
    event.Mouse(visible=False)

    if not (lgcLogMde):

        if lgcGrd:

            # Draw fixation grid circles:
            for objGrdCrcl in lstGrdCrcl:
                objGrdCrcl.draw(win=objWin)

            # Draw fixation grid lines:
            for objGrdLne in lstGrdLne:
                objGrdLne.draw(win=objWin)

        # Draw fixation dot & surround:
        objFixSrd.draw(win=objWin)
        objFix.draw(win=objWin)

        objWin.flip()

        # Wait for scanner trigger pulse & set clock after receiving trigger
        # pulse (scanner trigger pulse is received as button press ('5')):
        strTrgr = ['0']
        while strTrgr[0][0] != '5':
            # Check for keypress:
            lstTmp = event.getKeys(keyList=['5'], timeStamped=False)
            # Whether the list has the correct length (if nothing has happened,
            # lstTmp # will have length zero):
            if len(lstTmp) == 1:
                strTrgr = lstTmp[0][0]

    # Trigger pulse received, reset clock:
    objClck.reset(newT=0.0)

    # Main timer which represents the starting point of the experiment:
    varTme01 = objClck.getTime()

    # Time that is updated continuously to track time:
    varTme02 = objClck.getTime()

    # Timer used to control the logging of stimulus events:
    varTme03 = objClck.getTime()

    # Timer for grating stimulus polarity flicker:
    varTme04 = objClck.getTime()
    varTme05 = objClck.getTime()

    # Start of the experiment:
    for idxVol in range(varNumVol):

        # Show a grating during this volume?
        lgcOn = (aryDsg[idxVol, 0] == 1.0)

        # Set grating properties for current volume:
        if lgcOn:

            # Get stimulus properties from design matrix:
            varTmpPos = lstPos[idxVol]
            varTmpOri = aryDsg[idxVol, 2]
            varTmpCon = aryDsg[idxVol, 3]

            # Set bar properties:
            objBar.setPos(varTmpPos)
            objBar.setOri(varTmpOri)
            objBar.setColor((varTmpCon, varTmpCon, varTmpCon))

        # Still on the same volume?
        while varTme02 < (varTme01 + (float(idxVol + 1) * varTr)):

            # *****************************************************************
            # *** Draw stimuli

            # Draw fixation grid?
            if lgcGrd:

                # Draw fixation grid circles:
                for objGrdCrcl in lstGrdCrcl:
                    objGrdCrcl.draw(win=objWin)

                # Draw fixation grid lines:
                for objGrdLne in lstGrdLne:
                    objGrdLne.draw(win=objWin)

            # If a grating is shown, which orientation, position, and contrast?
            if lgcOn:

                # Draw grating.
                objBar.draw(win=objWin)

            # Don't draw fixation point in logging mode:
            if not (lgcLogMde):

                # Draw fixation dot & surround:
                objFixSrd.draw(win=objWin)
                objFix.draw(win=objWin)

            # Flip drawn objects to screen:
            objWin.flip()

            # Update current time:
            varTme02 = objClck.getTime()

            # Update current time:
            varTme05 = objClck.getTime()

            # *****************************************************************
            # *** Target control

            # Time for target?
            if ((varTmeTrgt <= varTme02) and (varTme02 <=
                                              (varTmeTrgt + varTrgtDur))):

                # Was the target off on the previous frame?
                if varSwtTrgt == 0:

                    # Switch the target on by changing the fixation dot colour.
                    objFix.fillColor = lstClrTrgt

                    # Log target event:
                    strTmp = ('TARGET scheduled for: ' + str(varTmeTrgt))
                    logging.data(strTmp)

                    # Once after target onset we set varSwtRspLog to one so
                    # that the participant's respond can be logged:
                    varSwtRspLog = 1

                    # Likewise, just after target onset we set the timer for
                    # response logging to the current time so that the response
                    # will only be counted as a hit in a specified time
                    # interval after target onset:
                    varTme03 = objClck.getTime()

                    # Switch the target switch.
                    varSwtTrgt = 1

            else:

                # No time for target.

                # Was the target just on?
                if varSwtTrgt == 1:

                    # Switch the target off (by changing fixation dot colour
                    # back to normal).
                    objFix.fillColor = lstClrFix

                    # Switch the target switch.
                    varSwtTrgt = 0

                    # Only increase the target  counter if the last target has
                    # not been reached yet:
                    if (varCntTrgt + 1) < varNumTrgt:

                        # Increase the target counter:
                        varCntTrgt = varCntTrgt + 1

                        # Time of next target event:
                        varTmeTrgt = vecTrgt[varCntTrgt]

            # Has the participant's response not been reported yet, and is it
            # still within the time window?
            if (varSwtRspLog == 1) and (varTme02 <= (varTme03 + varHitTme)):

                # Check for and log participant's response:
                lstRsps = event.getKeys(keyList=[strTrgtKey],
                                        timeStamped=False)

                # Check whether the list has the correct length:
                if len(lstRsps) == 1:

                    # Does the list contain the response key?
                    if lstRsps[0] == strTrgtKey:

                        # Log hit:
                        logging.data('Hit')

                        # Count hit:
                        varCntHit += 1

                        # After logging the hit, we have to switch off the
                        # response logging, so that the same hit is not logged
                        # over and over again:
                        varSwtRspLog = 0

            elif (varSwtRspLog == 1) and (varTme02 > (varTme03 + varHitTme)):

                # Log miss:
                logging.data('Miss')

                # Count miss:
                varCntMis += 1

                # If the subject does not respond to the target within time, we
                # log this as a miss and set varSwtRspLog to zero (so that the
                # response won't be logged as a hit anymore afterwards):
                varSwtRspLog = 0

            # *****************************************************************
            # *** Grating control

            # If a grating is shown, which orientation, position, and contrast?
            if lgcOn:

                # Change grating polarity:
                if (varTme04 + varGrtDur) <= varTme05:

                    if varSwtGrt == 0:
                        varSwtGrt = 1
                        objBar.contrast = 1.0

                    else:
                        varSwtGrt = 0
                        objBar.contrast = -1.0

                    # Remember time at which grating polarity was switched:
                    varTme04 = objClck.getTime()

            # Update current time:
            # varTme02 = objClck.getTime()

            # Update current time:
            # varTme05 = objClck.getTime()

        if lgcLogMde:

            # Temporary array for single frame (3 values per pixel - RGB):
            aryBuff[:, :, :] = objWin.getMovieFrame(buffer='front')

            # Clear frames (otherwise stack of frames will pile up in memory):
            objWin.movieFrames = []

            # We only save one value per pixel per volume (because the stimuli
            # are greyscale we discard 2nd and 3rd RGB dimension):
            aryRgb = aryBuff[:, :, 0]

            # Sample the relevant part of the screen (all the screen if in
            # full screen mode, central square otherwise).0
            aryRgb = aryRgb[:, varCrpX:(varPixX - varCrpX)]

            # Only sample every second pixel:
            aryRgb = aryRgb[::2, ::2]

            # On first frame, get pixel value of background intensity:
            if idxVol == 0:
                varBck = mode(aryRgb, axis=None)[0]

            # The stimulus log is supposed to contain information about where
            # the stimulus was presented on each volume, and at which contrast.
            # The pattern inside the stimulus (chequerboard) is not of
            # interest. Therefore, we create a logical array (True = stimulus
            # was present on this pixel).
            aryRgb = np.not_equal(aryRgb, varBck).astype(np.int8)

            # Contrast value on current volume:
            varTmpMax = int(np.around(255.0 * aryDsg[idxVol, 3]))

            # Rescale to range 0 to 255:
            aryRgb = np.multiply(aryRgb, varTmpMax).astype(np.uint8)

            # Hard copy:
            aryFrames[:, :, idxFrame] = np.copy(aryRgb)

            idxFrame = idxFrame + 1

        # Check whether exit keys have been pressed:
        if func_exit() == 1:
            break

    # *************************************************************************
    # *** Feedback

    logging.data('------End of the experiment.------')

    # Performance feedback only if there were any targets:
    if 0.0 < float(varCntHit + varCntMis):

        # Ratio of hits:
        varHitRatio = float(varCntHit) / float(varCntHit + varCntMis)

        # Present participant with feedback on her target detection
        # performance:
        if 0.99 < varHitRatio:
            # Perfect performance:
            strFeedback = ('You have detected ' + str(varCntHit) +
                           ' targets out of ' + str(varCntHit + varCntMis) +
                           '\n' + 'Keep up the good work :)')
        elif 0.9 < varHitRatio:
            # OKish performance:
            strFeedback = ('You have detected ' + str(varCntHit) +
                           ' targets out of ' + str(varCntHit + varCntMis) +
                           '\n' + 'There is still room for improvement ;)')
        else:
            # Low performance:
            strFeedback = ('You have detected ' + str(varCntHit) +
                           ' targets out of ' + str(varCntHit + varCntMis) +
                           '\n' + 'Please try to focus more :(')

        # Create text object:
        objTxtTmr = visual.TextStim(objWin,
                                    text=strFeedback,
                                    font="Courier New",
                                    pos=(0.0, 0.0),
                                    color=(1.0, 1.0, 1.0),
                                    colorSpace='rgb',
                                    opacity=1.0,
                                    contrast=1.0,
                                    ori=0.0,
                                    height=0.5,
                                    antialias=True,
                                    alignHoriz='center',
                                    alignVert='center',
                                    flipHoriz=False,
                                    flipVert=False,
                                    autoLog=False)

        if not (lgcLogMde):

            # Show feedback text:
            varTme04 = objClck.getTime()
            while varTme02 < (varTme04 + 3.0):
                objTxtTmr.draw()
                objWin.flip()
                varTme02 = objClck.getTime()

        # Log total number of hits and misses:
        logging.data(('Number of hits: ' + str(varCntHit)))
        logging.data(('Number of misses: ' + str(varCntMis)))
        logging.data(('Percentage of hits: ' +
                      str(np.around((varHitRatio * 100.0), decimals=1))))

    # *************************************************************************
    # *** End of the experiment

    # Make the mouse cursor visible again:
    event.Mouse(visible=True)

    # Close window:
    objWin.close()

    # *************************************************************************
    # *** Logging mode

    # Save screenshots (logging mode):
    if lgcLogMde:

        print('Saving screenshots')

        # Check whether target directory for frames (screenshots) for frames
        # exists, if not create it:
        lgcDir = os.path.isdir(strPthFrm)

        # If directory does not exist, create it:
        if not (lgcDir):
            # Create direcotry for segments:
            os.mkdir(strPthFrm)

        # Save stimulus frame array to npy file:
        np.savez_compressed((strPthFrm + os.path.sep + 'stimulus_log'),
                            aryFrames=aryFrames)

        # Loop through volumes and save PNGs:
        for idxVol in range(varNumVol):

            # print(('---Frame '
            #       + str(idxVol)
            #       + ' out of '
            #       + str(int(varNumVol))))

            # Create image:
            objImg = Image.fromarray(aryFrames[:, :, idxVol], mode='L')

            # File name (with leading zeros, e.g. '*_004' or '*_042'). For
            # consistency with earlier versions, the numbering of frames (PNG
            # files  corresponding to fMRI volumes) starts at '1' (not at '0').
            strTmpPth = (strPthFrm + os.path.sep + 'frame_' +
                         str(idxVol + 1).zfill(3) + '.png')

            # Save image to disk:
            objImg.save(strTmpPth)

    # *************************************************************************
    # *** Close everyting

    core.quit()
    monitors.quit()
    logging.quit()
    event.quit()
Example #28
0
    routineTimer.reset()

    # ------Prepare to start Routine "RandomStimuli"-------
    t = 0
    RandomStimuliClock.reset()  # clock
    frameN = -1
    continueRoutine = True
    # update component parameters for each repeat
    from psychopy import visual, core, event
    from PIL import Image
    import numpy as np
    import glob, os, random, copy, time

    aperture1 = visual.Aperture(win,
                                size=2,
                                pos=(4, -4),
                                ori=1,
                                shape='circle')
    aperture1.enable = False
    aperture2 = visual.Aperture(win,
                                size=2,
                                pos=(-4, 4),
                                ori=1,
                                shape='circle')
    aperture2.enable = False
    aperture3 = visual.Aperture(win, size=2, pos=(4, 4), ori=1, shape='circle')
    aperture3.enable = False
    aperture4 = visual.Aperture(win,
                                size=2,
                                pos=(-4, -4),
                                ori=1,
Example #29
0
    routineTimer.reset()

    # ------Prepare to start Routine "RandomStimuli"-------
    t = 0
    RandomStimuliClock.reset()  # clock
    frameN = -1
    continueRoutine = True
    # update component parameters for each repeat
    from psychopy import visual, core
    from PIL import Image
    import numpy as np
    import glob, os, random, copy, time

    aperture1 = visual.Aperture(win,
                                size=2,
                                pos=(4, -4),
                                ori=1,
                                shape='circle')
    #aperture1.enable = False
    aperture2 = visual.Aperture(win,
                                size=2,
                                pos=(-4, 4),
                                ori=1,
                                shape='circle')
    #aperture2.enable = False
    aperture3 = visual.Aperture(win, size=2, pos=(4, 4), ori=1, shape='circle')
    #aperture3.enable = False
    aperture4 = visual.Aperture(win,
                                size=2,
                                pos=(-4, -4),
                                ori=1,