Beispiel #1
0
    def __init__(self,
                 psychopy_disp,
                 density=16.7,
                 dot_speed=5.0,
                 frame_rate=60,
                 field_size=5.0,
                 field_scale=1.1):
        self.dot_speed = dot_speed
        self.frame_rate = frame_rate
        self.field_size = field_size

        field_width = field_size * field_scale
        self.n_dots = int(np.ceil(density * field_width**2 / frame_rate))
        # due to ElementArrayStim limitations, n_dots has to be divisible by n_sequences
        # so we artificially add extra dots in case it isn't divisible
        # (a couple of extra dots won't be a problem)
        self.n_dots += (self.n_sequences -
                        self.n_dots % self.n_sequences) % self.n_sequences

        n_elements = self.n_dots / self.n_sequences
        if (n_elements * self.n_sequences != self.n_dots):
            raise ValueError(
                'Check n_elements parameter provided to ElementArrayStim! '
                'It should be equal to n_dots/self.n_sequences, where n_dots is '
                'calculated based on density, frame rate and field width.')

        self.dot_stim = visual.ElementArrayStim(psychopy_disp,
                                                elementTex=None,
                                                fieldShape='circle',
                                                elementMask='circle',
                                                sizes=0.06,
                                                nElements=n_elements,
                                                units='deg',
                                                fieldSize=field_size)
Beispiel #2
0
    def __init__(self, win, length=21, size=3, max_alpha=0.5):
        self.win = win

        location = [0, 0]
        # generate loc array
        loc = np.array(location) + np.array((size, size)) // 2

        # array of rgbs for each element (2D)
        colors = np.ones((length ** 2, 3))
        colors[::2] = 0

        # array of coordinates for each element
        xys = []
        # populate xys
        low, high = length // -2, length // 2

        for y in range(low, high):
            for x in range(low, high):
                xys.append((size * x,
                            size * y))

        self.stim = visual.ElementArrayStim(win,
                                            xys=xys,
                                            fieldPos=loc,
                                            colors=colors,
                                            nElements=length ** 2,
                                            elementMask=None,
                                            elementTex=None,
                                            opacities=max_alpha,
                                            sizes=(size, size))

        self.stim.size = (size * length,
                     size * length)
Beispiel #3
0
def test_element_array_colors():
    # Create element array with two elements covering the whole window in two block colours
    obj = visual.ElementArrayStim(win,
                                  units="pix",
                                  fieldPos=(0, 0),
                                  fieldSize=(128, 128),
                                  fieldShape='square',
                                  nElements=2,
                                  sizes=[[64, 128], [64, 128]],
                                  xys=[[-32, 0], [32, 0]],
                                  elementMask=None,
                                  elementTex=None)
    # Iterate through color sets
    for colorSet in exemplars + tykes:
        for space in colorSet:
            if space not in colors.strSpaces and not isinstance(
                    colorSet[space], (str, type(None))):
                # Check that setting color arrays renders correctly
                obj.colorSpace = space
                col1 = np.array(colorSet[space]).reshape((1, -1))
                col2 = getattr(colors.Color('black'), space).reshape((1, -1))
                obj.colors = np.append(
                    col1, col2, 0
                )  # Set first color to current color set, second to black in same color space
                obj.opacity = 1  # Fix opacity at full as this is not what we're testing
                win.flip()
                obj.draw()
                utils.comparePixelColor(win,
                                        colors.Color(colorSet[space], space),
                                        coord=(10, 10))
                utils.comparePixelColor(win,
                                        colors.Color('black'),
                                        coord=(10, 100))
    def test_element_array(self):
        win = self.win
        if not win._haveShaders:
            pytest.skip(
                "ElementArray requires shaders, which aren't available")
        #using init
        thetas = numpy.arange(0, 360, 10)
        N = len(thetas)

        radii = numpy.linspace(0, 1.0, N) * self.scaleFactor
        x, y = pol2cart(theta=thetas, radius=radii)
        xys = numpy.array([x, y]).transpose()
        spiral = visual.ElementArrayStim(win,
                                         opacities=0,
                                         nElements=N,
                                         sizes=0.5 * self.scaleFactor,
                                         sfs=1.0,
                                         xys=xys,
                                         oris=-thetas)
        spiral.draw()
        #check that the update function is working by changing vals after first draw() call
        spiral.opacities = 1.0
        spiral.sfs = 3.0
        spiral.draw()
        "{}".format(spiral)  #check that str(xxx) is working
        win.flip()
        spiral.draw()
        utils.compareScreenshot('elarray1_%s.png' % (self.contextName), win)
        win.flip()
Beispiel #5
0
    def draw_stimuli(self):
        """ This function will draw the dots on the screen using the above
        initialized parameters.

        """

        self.stim = visual.ElementArrayStim(
            self.win,
            units='deg',
            fieldPos=(0.0, 0.0),
            fieldSize=(self.stimPos + self.stimRadius,
                       self.stimPos + self.stimRadius),
            fieldShape='circle',
            nElements=self.nDisks,
            sizes=self.stimRadius,
            xys=self.loc,
            rgbs=None,
            colors=[self.white] * self.nDisks,
            colorSpace='rgb',
            opacities=1.0,
            depths=0,
            fieldDepth=0,
            oris=0,
            sfs=1.0,
            contrs=1,
            phases=0,
            elementTex=np.random.random((self.tGrain, self.tGrain)),
            elementMask='circle',
            texRes=128,
            interpolate=True,
            name=None,
            autoLog=None,
            maskParams=None)
def createNoise(proportnNoise,win,fieldWidthPix,noiseColor): 
    #noiseColor, assumes that colorSpace='rgb', triple between -1 and 1
    numDots = int(proportnNoise*fieldWidthPix*fieldWidthPix)
    if numDots ==0:
        return None
    #create a matrix of all possible pixel locations, shuffle it, pick off the first numDots ones
    #0,0 is center of field
    possibleXcoords = -fieldWidthPix/2 + np.arange(fieldWidthPix) 
    possibleXcoords += fieldWidthPix/30 #adding one-tenth because for some mysterious reason not centered, I guess letters aren't drawn centered
    possibleYcoords = deepcopy(possibleXcoords)

    #allFieldCoords = expandgrid(possibleXcoords,possibleYcoords)
    allFieldCoords = expandGridNumpy( np.array([ possibleXcoords, possibleYcoords] )  )  #numpy array version so that can add a constat to all the x coordinates. Can't access all the x-coordinates if it is a list of tuples, like returned by expandgrid
    #shuffle it
    np.random.shuffle(allFieldCoords)
    dotCoords = allFieldCoords[0:numDots]

    #create opacity for each dot
    opacs = np.ones(numDots)#all opaque
    verticalAdjust = 3 #number of pixels to raise rectangle by. Using only uppercase letters and seem to be drawn above the line
    noise = visual.ElementArrayStim(win,units='pix', elementTex=None, elementMask=None,
        nElements=numDots, fieldSize=[fieldWidthPix,fieldWidthPix],
        fieldPos=(0.0, verticalAdjust),
        colorSpace='rgb',
        colors=noiseColor, #set to black
        xys= dotCoords, 
        opacities=opacs,
        sizes=1)
    return (noise,allFieldCoords,numDots) #Can just use noise, but if want to generate new noise of same coherence level quickly, can just shuffle coords
def run_scrsaver(depthBits):
    mon = monitors.Monitor(name='VIEWPixx LITE', width=38, distance=57)
    mon.setSizePix((1920, 1200))
    mon.save()  # if the monitor info is not saved

    win = visual.Window(fullscr=True, mouseVisible=False, bpc=(depthBits, depthBits, depthBits), depthBits=depthBits,
                        monitor=mon)
    kb = keyboard.Keyboard()

    if depthBits == 8:
        colorSpace = 'rgb255'
    elif depthBits == 10:
        colorSpace = 'rgb'
    else:
        raise ValueError("Invalid color depth!")

    while True:
        num = np.random.randint(5, high=10)
        rect = visual.ElementArrayStim(win, units='norm', nElements=num ** 2, elementMask=None, elementTex=None,
                                       sizes=(2 / num, 2 / num), colorSpace=colorSpace)
        rect.xys = [(x, y) for x in np.linspace(-1, 1, num, endpoint=False) + 1 / num for y in
                    np.linspace(-1, 1, num, endpoint=False) + 1 / num]

        rect.colors = [ColorPicker(depthBits=depthBits, unit='deg').newcolor(x)[1] for x in
                       np.random.randint(0, high=360, size=num ** 2)]
        rect.draw()
        win.mouseVisible = False
        win.flip()

        kb.clock.reset()
        if kb.getKeys():  # press any key to quit
            core.quit()
        else:
            time.sleep(3)  # change every 3 sec
 def patch_stim(self):  # standard and test stimuli
     patch = visual.ElementArrayStim(win=self.win,
                                     units='deg',
                                     nElements=self.patch_nmb,
                                     elementMask='circle',
                                     elementTex=None,
                                     sizes=self.cfg['patch_size'],
                                     colorSpace=self.ColorSpace)
     return patch
def patchstim(patchsize=0.5):
    patch = visual.ElementArrayStim(win=win,
                                    units='deg',
                                    nElements=npatch,
                                    elementMask='circle',
                                    elementTex=None,
                                    sizes=patchsize,
                                    colorSpace='rgb255')
    return patch
Beispiel #10
0
 def generate_texture(self):
     xys = self.element_position
     # for _ in range(self.number):
     #     xys.append([0, 0])  # Placeholder for now, because we'll set the real places later
     texture = (visual.ElementArrayStim(
         win=self.Renderer.display_window,
         fieldSize=self.Renderer.window_size(),
         elementMask=None,
         nElements=self.number,
         xys=xys,
         sizes=self.size,
         elementTex=self.source_image))
     return texture
Beispiel #11
0
    def new_array(self):
        """Initialize new stick positions."""
        initial_xys = self.poisson_disc_sample()
        n_sticks = len(initial_xys)
        sticks = visual.ElementArrayStim(self.win,
                                         xys=initial_xys,
                                         nElements=n_sticks,
                                         elementTex=None,
                                         elementMask="sqr",
                                         sizes=self.stick_sizes,
                                         autoLog=False)

        self.sticks = sticks
        self.n = n_sticks
 def patch_stim(self, xlim, ylim):  # standard and test stimuli
     n = int(np.sqrt(self.patch_nmb))
     pos = [[x, y] for x in np.linspace(xlim[0], xlim[1], n)
            for y in np.linspace(ylim[0], ylim[1], n)]
     patch = visual.ElementArrayStim(win=self.win,
                                     units='deg',
                                     fieldSize=self.cfg['field_size'],
                                     xys=pos,
                                     nElements=self.patch_nmb,
                                     elementMask='circle',
                                     elementTex=None,
                                     sizes=self.cfg['patch_size'],
                                     colorSpace=self.ColorSpace)
     return patch
    def make_ring(self, text_size=45):
        """ create the ring
        20210518 - use images instead to match eprime experiment
        makes self.ringimg['rew'] and self.ringimg['neu']
        see
        https://discourse.psychopy.org/t/the-best-way-to-draw-many-text-objects-rsvp/2758
        """

        # color and symbol for ring reward
        cues = {
            'neu': {
                'color': 'gray',
                'sym': '#'
            },
            'rew': {
                'color': 'green',
                'sym': '$'
            }
        }
        n_in_ring = 12
        el_rs = 250  # TODO: make relative to screen size?
        el_thetas = np.linspace(0, 360, n_in_ring, endpoint=False)
        el_xys = np.array(misc.pol2cart(el_thetas, el_rs)).T
        ringtext = visual.TextStim(win=self.win,
                                   units='pix',
                                   bold=True,
                                   height=text_size,
                                   text='$')  # '$' will be changed
        cap_rect_norm = [
            -(text_size / 2.0) / (self.win.size[0] / 2.0),  # left
            +(text_size / 2.0) / (self.win.size[1] / 2.0),  # top
            +(text_size / 2.0) / (self.win.size[0] / 2.0),  # right
            -(text_size / 2.0) / (self.win.size[1] / 2.0)  # bottom
        ]
        for k in ['rew', 'neu']:
            ringtext.text = cues[k]['sym']
            ringtext.color = cues[k]['color']
            buff = visual.BufferImageStim(win=self.win,
                                          stim=[ringtext],
                                          rect=cap_rect_norm)
            # img = (np.flipud(np.array(buff.image)[..., 0]) / 255.0 * 2.0 - 1.0)
            self.ringimg[k] = visual.ElementArrayStim(
                win=self.win,
                units="pix",
                nElements=n_in_ring,
                sizes=buff.image.size,
                xys=el_xys,
                # colors=cues[k]['color'],
                elementMask=None,
                elementTex=buff.image)
Beispiel #14
0
    def __init__(self):
        myDlg = gui.Dlg(title="Wisconsin Card Sorting Task",pos=(SZ[0]/2,SZ[1]/2))
        myDlg.addField('Subject ID:',1)
        #myDlg.addField('Number of Trials:',128)
        myDlg.show()#show dialog and wait for OK or Cancel
        vpInfo = myDlg.data
        self.vp = vpInfo[0]
        self.win = visual.Window(size=SZ,units='deg',fullscr=False,monitor=MON)
        self.mouse = event.Mouse(True,None,self.win)
        self.cards = []
        self.elems = []
        for i in range(4):
            self.cards.append(visual.Rect(self.win,CARDW,CARDH,fillColor='white',
                        pos = ((i-1.5)*(CARDX+CARDW),CARDY),lineColor='black',interpolate=False))
            self.elems.append(visual.ElementArrayStim(self.win,nElements=4,sizes=1.5,colors='black',
                         fieldPos = ((i-1.5)*(CARDX+CARDW),CARDY),elementTex=None))
        
        # Add the probe card to the screen
        self.cards.append(visual.Rect(self.win,CARDW,CARDH,fillColor='white',
            pos = TPOS,lineColor='black',interpolate=False))
        self.elems.append(visual.ElementArrayStim(self.win,nElements=4,sizes=1.5,colors='black',
            fieldPos = TPOS,elementTex=None))            
        
        # Make the piles
        for i in range(4):
            self.cards.append(visual.Rect(self.win,CARDW,CARDH,fillColor='grey',
                        pos = ((i-1.5)*(CARDX+CARDW),PrevCARDY),lineColor='black',interpolate=False))
            self.elems.append(visual.ElementArrayStim(self.win,nElements=4,sizes=1.5,colors='grey',
                        fieldPos = ((i-1.5)*(CARDX+CARDW),PrevCARDY),elementTex=None))
            

        self.text = visual.TextStim(self.win,pos=FPOS,height=2)
        if not os.path.exists('data'):
            os.makedirs('data')
        fname = os.path.join('data', 'wcst_s%03d_%s.csv' % (self.vp, time.strftime("%Y%m%d-%H%M%S")))
        self.output = open(fname, 'w')
        self.output.write('PartID\tTrialNum\tCard\tRule\tRespTime\tCorrect\n')
Beispiel #15
0
 def random_dot_motion(self, task_instance):
     clock = core.Clock()
     while clock.getTime() < STIMULUS_TIME:
         self.central_circle.draw()
         dots = task_instance.update_dots()
         visual.ElementArrayStim(
             win=self.win,
             nElements=len(dots),
             elementTex=None,
             elementMask="gauss",
             xys=[dot.xy for dot in dots],
             sizes=15,
             colors=WHITE,
         ).draw()
         self.win.flip()
         task_instance.move_dots()
Beispiel #16
0
def make_tokens(xys, indices, pos):
    """Creates an elementArrayStim based on given parameters"""
    # Select xys
    if len(xys) == len(indices): this_xys = xys  #no need to select indices
    else: this_xys = [xys[i] for i in indices]  #find corresponding x's,y's
    # Create the central ElementArrayStim array
    tokens = visual.ElementArrayStim(win,
                                     xys=this_xys,
                                     fieldShape='circle',
                                     fieldPos=pos,
                                     colors=whitish,
                                     nElements=len(this_xys),
                                     elementMask='circle',
                                     elementTex=None,
                                     sizes=(token_size[0], token_size[1]))
    return tokens
 def setElements(self,
                 name='default',
                 texture='square',
                 mask=None,
                 nElements=None,
                 sizes=None,
                 xys=None,
                 oris=None,
                 sfs=None,
                 phases=None,
                 colors=None,
                 opacities=None,
                 contrs=None):
     """
     Private wrapper for Psychopy ElementArrayStim.
     :param name: element array name
     :param texture: texture to render, could be string or numpy array. If string, right now support 'square' or 'rectangle'
     :param mask: mask to mask texture, should be numpy array or None.
     :param nElements: the number of elements to render.
     :param sizes: the size of elements, (nElements, 2) in pixel unit.
     :param xys: the position of elements, (nElements, 2) in pixel unit.
     :param oris: the orientation of elements, (nElements,)
     :param sfs: reserved
     :param phases: reserverd
     :param colors: the color of elements, (nElements, 3)
     :param opacities: the opacity of elements, (nElements,)
     :param contrs: the contrast of elements, (nElements,)
     :return:
     """
     if type(texture) is str:
         tex = self._SHAPES[texture]
         mask = None
     self.els[name] = visual.ElementArrayStim(self.win,
                                              units='pix',
                                              elementTex=tex,
                                              elementMask=mask,
                                              texRes=48,
                                              nElements=nElements,
                                              sizes=sizes,
                                              xys=xys,
                                              oris=oris,
                                              sfs=sfs,
                                              phases=phases,
                                              colors=colors,
                                              opacities=opacities,
                                              contrs=contrs)
Beispiel #18
0
 def test_element_array(self):
     win = self.win
     if not win._haveShaders:
         pytest.skip("ElementArray requires shaders, which aren't available")
     #using init
     thetas = numpy.arange(0,360,10)
     N=len(thetas)
     radii = numpy.linspace(0,1.0,N)*self.scaleFactor
     x, y = misc.pol2cart(theta=thetas, radius=radii)
     xys = numpy.array([x,y]).transpose()
     spiral = visual.ElementArrayStim(win, nElements=N,sizes=0.5*self.scaleFactor,
         sfs=3.0, xys=xys, oris=thetas)
     spiral.draw()
     win.flip()
     spiral.draw()
     utils.compareScreenshot('elarray1_%s.png' %(self.contextName), win)
     win.flip()
 def __init__(self, win,nDots, minDistance, maxDistance, dotSize, mu, sigma, pixPerSecond,flipcos = False):
     self.win = win
     self.nDots = nDots
     self.minDistance = minDistance
     self.maxDistance = maxDistance
     self.dotSize = dotSize
     self.pixPerSecond = pixPerSecond
     self.mu = mu
     self.sigma = sigma
     self.rotationMatrix = np.array([[np.cos(np.pi),np.sin(np.pi)],[-np.sin(np.pi),np.cos(np.pi)]])
     
     self.dotPositions = []        
     for dot in range(self.nDots):
         overlap = True 
         while overlap: 
             r = random.uniform(self.minDistance,self.maxDistance**2) 
             randomAngle=random.uniform(0,1)*2*np.pi
             # calculate x and y position 
             dot_x = np.sqrt(r)*np.cos(randomAngle)
             dot_y = np.sqrt(r)*np.sin(randomAngle)
             
             if not self.dotPositions:
                 break 
            
             diff = np.array(self.dotPositions) - np.array([dot_x,dot_y])
             tmp = abs(diff) < self.dotSize 
             if not True in tmp[:,1] & tmp[:,0]:
                 overlap = False 
     
         # append to list 
         self.dotPositions.append([dot_x, dot_y])    
         
     self.dotPositions = np.array(self.dotPositions)    
     if self.sigma == 0:
         dotDirections = np.array(self.nDots*[self.mu])
     else:
         dotDirections = np.random.normal(self.mu,self.sigma,self.nDots)
     if flipcos:
         self.dotVelocities = np.column_stack((np.sin(np.deg2rad(dotDirections)),np.cos(np.deg2rad(dotDirections))))
     else:
         self.dotVelocities = np.column_stack((np.cos(np.deg2rad(dotDirections)),np.sin(np.deg2rad(dotDirections))))
     
     #create stimulus 
     self.stim = visual.ElementArrayStim(self.win, elementTex = 'none',elementMask = 'circle', nElements=self.nDots, 
                                     sizes=self.dotSize, xys = self.dotPositions,colors = (1,1,1),contrs = 0.5) 
Beispiel #20
0
    def update_cal_target(self):
        ''' make sure target stimuli is already memory when being used by draw_cal_target '''

        if self.calTarget is 'picture':
            if self.pictureTargetFile is None:
                print(
                    'ERROR: Clibration target is None, please provide a picture'
                )
                core.quit()
            else:
                self.calibTar = visual.ImageStim(self.display,
                                                 self.pictureTargetFile,
                                                 size=self.targetSize)

        elif self.calTarget is 'spiral':
            thetas = numpy.arange(0, 1440, 10)
            N = len(thetas)
            radii = numpy.linspace(0, 1.0, N) * self.targetSize
            x, y = pol2cart(theta=thetas, radius=radii)
            xys = numpy.array([x, y]).transpose()
            self.calibTar = visual.ElementArrayStim(self.display,
                                                    nElements=N,
                                                    sizes=self.targetSize,
                                                    sfs=3.0,
                                                    xys=xys,
                                                    oris=-thetas)
        elif self.calTarget is 'movie':
            if self.movieTargetFile is None:
                print(
                    'ERROR: Clibration target is None, please provide a movie clip'
                )
                core.quit()
            else:
                self.calibTar = visual.MovieStim3(self.display,
                                                  self.movieTargetFile,
                                                  loop=True,
                                                  size=self.targetSize)

        else:  #'use the default 'circle'
            self.calibTar = visual.Circle(self.display,
                                          radius=self.targetSize / 2,
                                          lineColor=self.foregroundColor,
                                          fillColor=self.backgroundColor,
                                          lineWidth=self.targetSize / 2.0,
                                          units='pix')
Beispiel #21
0
def flash_init(win, position=[0, 0], square_size=10, columns=10, rows=10):
    global flash  # The flash stimulus (an array of flashing squares)
    red = [1, -1, -1]
    green = [-1, 1, -1]
    blue = [-1, -1, 1]
    yellow = [1, 0.97, -0.55]
    black = [-1, -1, -1]
    color_set = [red, green, blue, yellow, black]
    cell_number = columns * rows
    by_color = int(np.floor(float(cell_number) / len(color_set)))
    # fill an array with colors. Each color should appear approximatively the same number of times.
    f_colors = []
    for c in color_set:
        for i in range(by_color):
            f_colors.append(c)
    shuffle(color_set)
    i = cell_number - len(f_colors)
    while i > 0:
        f_colors.append(color_set[i])
        i -= 1
    # randomize color order.
    shuffle(f_colors)
    # fill an array with coordinate for each color square. First square should be at the upper left
    # and next should follow from left to right and up to down.
    xys = []
    x_left = (1 - columns) * square_size / 2
    y_top = (1 - rows) * square_size / 2
    for l in range(rows):
        for c in range(columns):
            xys.append((x_left + c * square_size, y_top + l * square_size))
    flash = visual.ElementArrayStim(win=win,
                                    fieldPos=position,
                                    fieldShape='sqr',
                                    nElements=cell_number,
                                    sizes=square_size,
                                    xys=xys,
                                    colors=f_colors,
                                    elementTex=None,
                                    elementMask=None,
                                    name='flash',
                                    autoLog=False)
Beispiel #22
0
    def make_stimulus(self):

        self.stimulus = visual.ElementArrayStim(
            self.screen,
            elementTex='sqr',
            elementMask='raisedCos',
            maskParams={'fringeWidth': 0.6},
            nElements=1,
            sizes=self.session.standard_parameters['stimulus_size'] *
            self.session.pixels_per_degree,
            sfs=self.session.standard_parameters['stimulus_base_spatfreq'],
            xys=np.array((self.trial_settings['trial_position_x'] *
                          self.session.pixels_per_degree,
                          self.trial_settings['trial_position_y'] *
                          self.session.pixels_per_degree))[np.newaxis, :],
            oris=self.trial_settings['base_ori'],
            colors=ct.lab2psycho([
                self.trial_settings['base_color_lum'],
                self.trial_settings['base_color_a'],
                self.trial_settings['base_color_b']
            ]),
            colorSpace='rgb',
            units='pix')
Beispiel #23
0
def newRand():

    #Anzahl der Punkte
    n_dots = 100000

    #Position der Punkte
    dot_xys = []

    for dot in range(n_dots):

        dot_x = random.uniform(-300, 100)
        dot_y = random.uniform(-200, 200)

        dot_xys.append([dot_x, dot_y])
        #dot_xys = np.random.normal(0,1,[256,256])

#Gradient der Punkte
    randomGradient = []

    for dot in range(n_dots):

        randomNumber = random.gauss(127.5, 100)

        randomGradient.append([randomNumber, randomNumber, randomNumber])

#Erstellen der Punkte
    dot_stim = visual.ElementArrayStim(win=v_winObj,
                                       units="pix",
                                       nElements=n_dots,
                                       elementTex=None,
                                       elementMask="gauss",
                                       xys=dot_xys,
                                       sizes=3,
                                       colors=randomGradient,
                                       colorSpace='rgb255')
    return dot_stim
Beispiel #24
0
# --- Create Stimulus Array, pre-allocate and configure square flickers
number_stimulus = 5
stimulus_sizes = np.array([3] * number_stimulus)
stimulus_color_ON = np.array([1, 1, 1] * number_stimulus)
stimulus_color_ON = np.reshape(stimulus_color_ON, [number_stimulus, 3])
stimulus_color_OFF = stimulus_color_ON * -1

stimulus_locations = np.array([[-25, 0], [25, 0], [0, 13], [0, -13], [-25,
                                                                      13]])
stimulus_array = visual.ElementArrayStim(window_handle,
                                         fieldPos=(0.0, 0.0),
                                         units='cm',
                                         fieldSize=[1920, 1080],
                                         sizes=stimulus_sizes,
                                         fieldShape='sqr',
                                         xys=stimulus_locations,
                                         nElements=number_stimulus,
                                         sfs=0,
                                         elementTex=None,
                                         elementMask=None,
                                         colors=stimulus_color_ON,
                                         colorSpace='rgb')

# --- Configure execution time for the flickering loop
target_time = 20
time.clock()  # First clock call that serves as time reference
clock_object = core.Clock()
elapsed_time = clock_object.getTime()

# --- Enable frame monitoring and logging (to detect drop frames)
window_handle.flip()
def doRSVPStim(trial):
    '''
    ONLY DOES ONE CUE AT THE MOMENT

    This function generates the stimuli for each trial. The word "frame" here refers to a set of simultaneous RSVP stimuli. I'll use "refresh" to refer to monitor refreshes.
    Using the parameters for the current trial:
        - Work out the temporal position of the cue(s)
        - Shuffle the order of the letters
        - Calculate the position and cortically-magnified size for each stream
        - draw and buffer preCues
        - Capture each stream's pixels on each frame using bufferImageStim
        - Collate each frame's pixels so that all stimuli are represented by the same matrix of pixels. Put the cue in there if it's the cued frame
        - pass the matrix of pixels to elementarraystim
    '''
    
    global cue
    
    nStreams = trial['nStreams']
    numTargets = trial['numToCue']  
    
    cuedFrame = trial['cue0temporalPos']
    cuedStream = np.random.choice(np.arange(nStreams), 1)

    cue.pos = calcStreamPos(
                trial = trial, 
                cueOffsets = cueOffsets, 
                streami = cuedStream, 
                streamOrNoise = False
                )
    cue = corticalMagnification.corticalMagnification(cue, 0.9810000000000002, cue = True) #this is the cuesize from the original experiment

    preCues = list()
    preCues.append(cue)

    if trial['cueSpatialPossibilities'] == 2:
        preCue = visual.Circle(myWin, 
                     radius=cueRadius,#Martini used circles with diameter of 12 deg
                     lineColorSpace = 'rgb',
                     lineColor=letterColor,
                     lineWidth=2.0, #in pixels
                     units = 'deg',
                     fillColorSpace = 'rgb',
                     fillColor=None, #beware, with convex shapes fill colors don't work
                     pos= [-5,-5], #the anchor (rotation and vertices are position with respect to this)
                     interpolate=True,
                     autoLog=False)#this stim changes too much for autologging to be useful
       
        preCue.pos = calcStreamPos(
            trial = trial,
            cueOffsets = cueOffsets,
            streami = cuedStream-4,
            streamOrNoise = False
        )
        
        preCue = corticalMagnification.corticalMagnification(preCue, 0.9810000000000002, cue = True)
        
        preCues.append(preCue)

    elif trial['cueSpatialPossibilities'] == 8:
        for i in range(1,8):
            preCue = visual.Circle(myWin, 
                     radius=cueRadius,#Martini used circles with diameter of 12 deg
                     lineColorSpace = 'rgb',
                     lineColor=letterColor,
                     lineWidth=2.0, #in pixels
                     units = 'deg',
                     fillColorSpace = 'rgb',
                     fillColor=None, #beware, with convex shapes fill colors don't work
                     pos= [-5,-5], #the anchor (rotation and vertices are position with respect to this)
                     interpolate=True,
                     autoLog=False)#this stim changes too much for autologging to be useful
        
            
            preCue.pos = (calcStreamPos(
                trial = trial,
                cueOffsets = cueOffsets,
                streami = cuedStream-i,
                streamOrNoise = False
            ))
            
            preCue = corticalMagnification.corticalMagnification(preCue, 0.9810000000000002, cue = True)
            preCues.append(preCue)            

    print('cueFrame = ' + str(cuedFrame))

    preCueStim = preTrial[int(baseAngleCWfromEast/anglesMustBeMultipleOf)] + preCues + [fixatnPoint]

    preCueFrame = visual.BufferImageStim(
                    win = myWin,
                    stim = preCueStim)
    
    preCueFrame = np.flipud(np.array(preCueFrame.image)[..., 0]) / 255.0 * 2.0 - 1.0 #Via djmannion. This converts the pixel values from [0,255] to [-1,1]. I think 0 is middle grey. I'll need to change this to match the background colour eventually
        
    preCueFrame = np.pad(
            array=preCueFrame,
            pad_width=pad_amounts, #See 'Buffered image size dimensions' section
            mode="constant",
            constant_values=0.0
        )

    preCueFrame =visual.ElementArrayStim(
            win = myWin,
            units = 'pix',
            nElements=1,
            xys = [[0,0]],
            sizes=preCueFrame.shape,
            elementTex=preCueFrame,
            elementMask = 'none'
        )


    streamPositions = list() #Might need to pass this to elementArrayStim as xys. Might not though


    streamLetterIdxs = np.empty( #use an array so I can select columns (frames) for buffering. This is an empty array that will eventually have the
                                 #letter indexes for each stream. Selecting a column gives us all streams at a particular frame. Selecting a row gives us
                                 #all frames for a particular stream
        shape = (nStreams,numLettersToPresent),
        dtype = int
        )

    streamLetterIdentities = np.empty( #Letter identities for these streams
        shape = (nStreams,numLettersToPresent),
        dtype = str
        )

    for thisStream in xrange(nStreams):
        thisSequence = np.arange(24)
        np.random.shuffle(thisSequence)
        theseIdentities = [potentialLetters[idx] for idx in thisSequence]
        streamLetterIdxs[thisStream,:] = thisSequence
        streamLetterIdentities[thisStream,:] = theseIdentities
        #print('For stream %(streamN)d the letters are: %(theseLetters)s' % {'streamN':thisStream, 'theseLetters':''.join(theseIdentities)})

    correctIdx = streamLetterIdxs[cuedStream,cuedFrame] 
    print('correctIdx')
    print(correctIdx)
    correctLetter = alphabetHelpers.numberToLetter(correctIdx, potentialLetters) #potentialLetters is global

    frameStimuli = list() #A list of elementArrayStim objects, each represents a frame. Drawing one of these objects will draw the letters and the cue for that frame

    for thisFrame in xrange(numLettersToPresent):
        theseStimuli = streamLetterIdxs[:,thisFrame] #The alphabetical indexes of stimuli to be shown on this frame
        
        stimuliToDraw = list() #Can pass a list to bufferimageStim!
        stimuliToDraw.append(fixatn)
        stimuliToDrawCounterPhase = list()
        stimuliToDrawCounterPhase.append(fixatnCounterphase)

        for thisStream in xrange(nStreams):
            cueThisFrame = thisStream == cuedStream and thisFrame == cuedFrame #If true, draw the cue and capture that too

            thisLetterIdx = theseStimuli[thisStream] #The letter index for this particular stream on this particular frame
            
            thisStreamStimulus = streamTextObjects[thisStream,thisLetterIdx] #The text object for this stream
            
            thisPos = calcStreamPos(
                trial = trial, 
                cueOffsets = cueOffsets, 
                streami = thisStream, 
                streamOrNoise = False
                )

            thisStreamStimulus.pos = thisPos

            stimuliToDraw.append(thisStreamStimulus)
            stimuliToDrawCounterPhase.append(thisStreamStimulus)

            if cueThisFrame and cueType == 'exogenousRing':
                stimuliToDraw.append(cue)
                stimuliToDrawCounterPhase.append(cue)
        
        buff = visual.BufferImageStim( #Buffer these stimuli
            win = myWin,
            stim = stimuliToDraw
            )
        
        
        buff = np.flipud(np.array(buff.image)[..., 0]) / 255.0 * 2.0 - 1.0 #Via djmannion. This converts the pixel values from [0,255] to [-1,1]. I think 0 is middle grey. I'll need to change this to match the background colour eventually
        
        buff = np.pad(
            array=buff,
            pad_width=pad_amounts, #See 'Buffered image size dimensions' section
            mode="constant",
            constant_values=0.0
        )
        
        thisFrameStimuli = visual.ElementArrayStim( #A stimulus representing this frame with the fixation at full luminance
            win = myWin,
            units = 'pix',
            nElements=1,
            xys = [[0,0]],
            sizes=buff.shape,
            elementTex=buff,
            elementMask = 'none'
            )
            
        buff = visual.BufferImageStim( #Buffer these stimuli
            win = myWin,
            stim = stimuliToDrawCounterPhase
            )
        
        
        buff = np.flipud(np.array(buff.image)[..., 0]) / 255.0 * 2.0 - 1.0 #Via djmannion. This converts the pixel values from [0,255] to [-1,1]. I think 0 is middle grey. I'll need to change this to match the background colour eventually
        
        buff = np.pad(
            array=buff,
            pad_width=pad_amounts, #See 'Buffered image size dimensions' section
            mode="constant",
            constant_values=0.0
        )
        

        thisFrameStimuliCounterPhase = visual.ElementArrayStim( #A stimulus representing this frame with the fixation phase reversed
            win = myWin,
            units = 'pix',
            nElements=1,
            xys = [[0,0]],
            sizes=buff.shape,
            elementTex=buff,
            elementMask = 'none'
            )        

        frameStimuli.append([thisFrameStimuli, thisFrameStimuliCounterPhase])

    ts = []
    
    waiting = True
    myMouse.setVisible(waiting)
    
    while waiting:
        startTrialStimuli.draw()
        startTrialBox.draw()
        myWin.flip()
        if myMouse.isPressedIn(startTrialBox):
            waiting = False

    myMouse.setVisible(waiting)

    if eyetracking: 
        tracker.startEyeTracking(nDone,True,widthPix,heightPix) #start recording with eyetracker  

    myWin.flip(); myWin.flip()#Make sure raster at top of screen (unless not in blocking mode), and give CPU a chance to finish other tasks
    preCueFrame.draw()
    myWin.flip()
    core.wait(.25)
    myWin.flip
    core.wait(.5)
    fixatn.draw()
    myWin.flip()
    core.wait(1)
    


    t0 = trialClock.getTime()
    for n in xrange(trialDurFrames):
        oneFrameOfStim(n, frameStimuli)
        myWin.flip()
        ts.append(trialClock.getTime() - t0)
    
    if eyetracking:
        tracker.stopEyeTracking()
        print('stopped tracking')
    return streamLetterIdxs, streamLetterIdentities, correctLetter, ts, cuedStream, cuedFrame
Beispiel #26
0
    def __init__(self, session, bar_width_ratio, grid_pos):
        """ Initializes a Stim object. 

        Parameters
        ----------
        session : exptools Session object
            A Session object (needed for metadata)
        bar_width_ratio : float
            Ratio of screen dim to use as bar width
        grid_pos : array
            List/array of grid positions within display, to select a subset that will be the bar
            
        """

        # general parameters
        self.session = session

        self.bar_width_pix = self.session.screen * bar_width_ratio

        self.grid_pos = grid_pos

        self.condition_settings = self.session.settings['stimuli'][
            'conditions']

        # define element arrays here, with settings of background
        # will be updated later when drawing

        # number of elements
        self.nElements = self.grid_pos.shape[0]

        # element positions
        self.element_positions = self.grid_pos

        # element sizes
        element_sizes_px = tools.monitorunittools.deg2pix(
            self.session.settings['stimuli']['element_size'],
            self.session.monitor)
        self.element_sizes = np.ones((self.nElements)) * element_sizes_px

        # elements spatial frequency
        self.element_sfs = np.ones(
            (self.nElements)) * self.condition_settings['background'][
                'element_sf']  # in cycles/gabor width

        # element orientation (half ori1, half ori2)
        ori_arr = np.concatenate(
            (np.ones((math.floor(self.nElements * .5))) *
             self.condition_settings['background']['element_ori'][0],
             np.ones((math.ceil(self.nElements * .5))) *
             self.condition_settings['background']['element_ori'][1]))

        # add some jitter to the orientations
        self.element_ori = jitter(
            ori_arr,
            max_val=self.condition_settings['background']['ori_jitter_max'],
            min_val=self.condition_settings['background']['ori_jitter_min'])

        np.random.shuffle(self.element_ori)  # shuffle the orientations

        # element contrasts
        self.element_contrast = np.ones(
            (self.nElements
             )) * self.condition_settings['background']['element_contrast']

        # element colors
        self.element_color = np.ones(
            (int(np.round(self.nElements)), 3)) * np.array(
                self.condition_settings['background']['element_color'])

        self.session.background_array = visual.ElementArrayStim(
            win=self.session.win,
            nElements=self.nElements,
            units='pix',
            elementTex='sin',
            elementMask='gauss',
            sizes=self.element_sizes,
            sfs=self.element_sfs,
            xys=self.element_positions,
            oris=self.element_ori,
            contrs=self.element_contrast,
            colors=self.element_color,
            colorSpace=self.session.settings['stimuli']['colorSpace'])

        self.session.bar0_array = visual.ElementArrayStim(
            win=self.session.win,
            nElements=self.nElements,
            units='pix',
            elementTex='sin',
            elementMask='gauss',
            sizes=self.element_sizes,
            sfs=self.element_sfs,
            xys=self.element_positions,
            oris=self.element_ori,
            contrs=self.element_contrast,
            colors=self.element_color,
            colorSpace=self.session.settings['stimuli']['colorSpace'])
    def run_trial(self, rot, cond, std, count):
        # set two reference
        leftRef = self.patch_ref(theta=cond['leftRef'],
                                 pos=self.cfg['leftRef.pos'])
        rightRef = self.patch_ref(theta=cond['rightRef'],
                                  pos=self.cfg['rightRef.pos'])

        # randomly assign patch positions: upper (+) or lower (-)
        patchpos = [self.cfg['standard.ylim'], self.cfg['test.ylim']]
        rndpos = patchpos.copy()
        np.random.shuffle(rndpos)

        sPatch = self.patch_stim(self.cfg['standard.xlim'], rndpos[0])
        tPatch = self.patch_stim(self.cfg['test.xlim'], rndpos[1])

        # set colors of two stimuli
        standard = cond['standard']  # standard should be fixed
        test = standard + rot
        sPatch.colors, tPatch.colors = self.choose_con(standard, test, std)

        # fixation cross
        fix = visual.TextStim(self.win,
                              text="+",
                              units='deg',
                              pos=[0, 0],
                              height=0.5,
                              color='black',
                              colorSpace=self.ColorSpace)
        # number of trial
        num = visual.TextStim(self.win,
                              text="trial " + str(count),
                              units='deg',
                              pos=[12, -10],
                              height=0.4,
                              color='black',
                              colorSpace=self.ColorSpace)

        trial_time_start = time.time()
        # first present references
        fix.draw()
        num.draw()
        leftRef.draw()
        rightRef.draw()
        self.win.flip()
        core.wait(1.0)

        # then present the standard and the test stimuli as well
        fix.draw()
        num.draw()
        leftRef.draw()
        rightRef.draw()
        sPatch.draw()
        tPatch.draw()
        self.win.flip()
        core.wait(self.trial_dur)

        fix.draw()
        self.win.flip()
        core.wait(0.2)  # 0.2 sec gray background
        react_time_start = time.time()

        # refresh the window and show a colored checkerboard
        horiz_n = 30
        vertic_n = 20
        rect = visual.ElementArrayStim(self.win,
                                       units='norm',
                                       nElements=horiz_n * vertic_n,
                                       elementMask=None,
                                       elementTex=None,
                                       sizes=(2 / horiz_n, 2 / vertic_n),
                                       colorSpace=self.ColorSpace)
        rect.xys = [
            (x, y)
            for x in np.linspace(-1, 1, horiz_n, endpoint=False) + 1 / horiz_n
            for y in np.linspace(-1, 1, vertic_n, endpoint=False) +
            1 / vertic_n
        ]

        rect.colors = [
            self.ColorPicker.newcolor(theta=x)[1]
            for x in np.random.randint(0, high=360, size=horiz_n * vertic_n)
        ]
        rect.draw()
        self.win.flip()
        core.wait(0.5)  # 0.5 sec checkerboard

        judge = None
        react_time_stop = -1
        kb = keyboard.Keyboard()
        get_keys = kb.getKeys(['right', 'left', 'escape'
                               ])  # if response during the checkerboard
        if ('left' in get_keys
                and rot * rndpos[0][0] > 0) or ('right' in get_keys
                                                and rot * rndpos[0][0] < 0):
            judge = 1  # correct
            react_time_stop = time.time()
        elif ('left' in get_keys
              and rot * rndpos[0][0] < 0) or ('right' in get_keys
                                              and rot * rndpos[0][0] > 0):
            judge = 0  # incorrect
            react_time_stop = time.time()
        if 'escape' in get_keys:
            config_tools.write_xrl(self.subject, break_info='userbreak')
            core.quit()

        self.win.flip()
        fix.draw()
        self.win.flip()

        if judge is None:  # if response after the checkerboard
            for wait_keys in event.waitKeys():
                if (wait_keys == 'left' and rot * rndpos[0][0] > 0) or (
                        wait_keys == 'right' and rot * rndpos[0][0] < 0):
                    judge = 1  # correct
                    react_time_stop = time.time()
                elif (wait_keys == 'left' and rot * rndpos[0][0] < 0) or (
                        wait_keys == 'right' and rot * rndpos[0][0] > 0):
                    judge = 0  # incorrect
                    react_time_stop = time.time()
                elif wait_keys == 'escape':
                    config_tools.write_xrl(self.subject,
                                           break_info='userbreak')
                    core.quit()

        react_time = react_time_stop - react_time_start

        return judge, react_time, trial_time_start
Beispiel #28
0
# divide the dotSpeed by the refresh rate
dotSpeed = dotSpeed / refr_rate

# log stimulus properties defined above
logFile.write('nDots=' + unicode(nDots) + '\n')
logFile.write('speed=' + unicode(dotSpeed) + '\n')
logFile.write('dotSize=' + unicode(dotSize) + '\n')
logFile.write('fieldSizeRadius=' + unicode(FieldSizeRadius) + '\n')

# initialise moving dot stimuli
dotPatch = visual.ElementArrayStim(myWin,
                                   fieldPos=(0.0, 0.0),
                                   autoLog=False,
                                   elementTex=None,
                                   name='dotPatch',
                                   fieldShape='circle',
                                   elementMask='circle',
                                   nElements=int(nDots),
                                   sizes=dotSize,
                                   units='deg',
                                   fieldSize=FieldSizeRadius * 2,
                                   colors=dotColor)

# fixation dot
dotFix = visual.Circle(
    myWin,
    autoLog=False,
    name='dotFix',
    units='pix',
    radius=5,
    fillColor=[1.0, 0.0, 0.0],
    lineColor=[1.0, 0.0, 0.0],
    def __init__(self, screen, trial, session, trial_params):
        # parameters

        self.trial = trial
        self.session = session
        self.screen = screen
        self.size_pix = session.standard_parameters[
            'stimulus_size'] * session.pixels_per_degree

        # self.orientation = orientation	# convert to radians immediately, and use to calculate rotation matrix

        self.trial_params = trial_params

        self.orientations = []
        self.positions = []
        self.colors = []

        self.element_array = []

        for i, c in enumerate(self.trial_params):
            if len(c):

                #self.element_array.append(visual.GratingStim(self.screen, tex = 'sqr', mask = 'raisedCos', maskParams = {'fringeWidth': 0.6}, texRes = 1024, sf = self.session.standard_parameters['stimulus_base_spatfreq'], ori = c[0], units = 'pix',  size = (self.size_pix, self.size_pix), pos = (self.session.stimulus_positions[i][0]*self.session.pixels_per_degree, self.session.stimulus_positions[i][1]*self.session.pixels_per_degree), colorSpace = 'rgb', color = c[1:]))

                # self.colors.append([rgbc*255.0 for rgbc in colorsys.hls_to_rgb(c[1], .5, 1)])
                self.colors.append(c[1:])
                self.positions.append((self.session.stimulus_positions[i][0] *
                                       session.pixels_per_degree,
                                       self.session.stimulus_positions[i][1] *
                                       session.pixels_per_degree))
                self.orientations.append(c[0])

        self.period = session.standard_parameters[
            'mapper_stimulus_duration'] * session.standard_parameters['TR']
        self.refresh_frequency = self.period / session.standard_parameters[
            'mapper_n_redraws']

        self.phase = 0
        # bookkeeping variables
        self.eccentricity_bin = -1
        self.redraws = 0
        self.last_redraw = 0
        self.frames = 0
        self.last_stimulus_present_for_task = 0

        # psychopy stimuli
        self.fix_gray_value = (0, 0, 0)

        # self.populate_stimulus()

        # make this stimulus array a session variable, in order to have to create it only once...
        # if not hasattr(session, 'element_array'):
        self.element_array = None
        if len(self.colors):
            self.element_array = visual.ElementArrayStim(
                screen,
                elementTex='sqr',
                elementMask='raisedCos',
                maskParams={'fringeWidth': 0.6},
                nElements=len(self.positions),
                sizes=session.standard_parameters['stimulus_size'] *
                session.pixels_per_degree,
                sfs=session.standard_parameters['stimulus_base_spatfreq'],
                xys=self.positions,
                oris=self.orientations,
                colors=self.colors,
                colorSpace='rgb',
                units='pix')
Beispiel #30
0
    event_clock.reset()
    win.flip()

    # Set up memory probe screen
    xys = []
    loop_radius = 8
    n_circ = 360
    for theta in np.linspace(0, 360, n_circ, endpoint=False):
        xys.append((loop_radius * np.cos(theta * np.pi / 180),
                    loop_radius * np.sin(theta * np.pi / 180)))

    stim = visual.ElementArrayStim(win,
                                   nElements=n_circ,
                                   sizes=0.9,
                                   xys=xys,
                                   elementTex=None,
                                   elementMask="circle",
                                   colors=rgb.reshape(n_circ, 3),
                                   colorSpace='rgb',
                                   interpolate=True)

    mask1 = visual.Circle(win, radius=loop_radius - 0.5, units='deg')
    mask1.units = 'deg'
    mask2 = visual.Circle(win, radius=loop_radius + 0.5, units='deg')
    mask2.units = 'deg'

    while event_clock.getTime() < 0.1:
        pass
    event_clock.reset()
    win.flip()
    probe = random.sample(np.arange(0, trial.num_stimuli), 1)[0]