Hey all,
I have constructed different types of optic flow stimuli using elementarraystim. So far, I have successfully implemented translational, rotational, and radial dot motion into my code. Basically, what I did was to update the array of dot location with pre-specified speed value for each motion type. When I run the code, however, I observe that dots that are engaging in rotational motion move in a relatively slower speed compared to other types of motion. Although I suspect the problem with being related to differences in polar and cartesian velocity (along with my lack of understanding of pol2cart function), I am having trouble in conceptually understanding the source of the problem.
I would be so glad if anyone can share me his/her knowledge related to the problem stated above. I’ve attached my code below. Program randomly picks the motion type and runs it for a total of 2 seconds (inverting direction after 1 second).
Suggestions that are irrelevant to the speed difference problem but potentially helpful for optimizing the code will also be appreciated.
Thanks a lot!
Gorkem
from __future__ import division # so that 1/3=0.333 instead of 1/3=0
from psychopy import visual, core, data, event, logging, sound, gui
from psychopy.constants import * # things like STARTED, FINISHED
import numpy # whole numpy lib is available, prepend 'np.'
from numpy import sin, cos, tan, log, log10, pi, average, sqrt, std, deg2rad, rad2deg, linspace, asarray
from numpy.random import random, randint, normal, shuffle
import os # handy system and path functions
from random import choice, randrange, shuffle, uniform
from psychopy.tools.coordinatetools import pol2cart, cart2pol
import time
from psychopy.tools.filetools import fromFile, toFile
win = visual.Window([1680, 1050], units='deg',
monitor='Umram', color='black', fullscr = False)
# experiment details
refRate = 60 # 1 second
nTrials = 15
stimDur = refRate # stimulus duration = 2 seconds
# important parameters
dotsN = 40
fieldSize = 3 # 3x3 square dot field
elemSize = 0.25
speed = 7/60 # 7 degree/seconds
dotsX = numpy.random.uniform(low=-fieldSize, high=fieldSize, size=(dotsN,)) # array of random float numbers between fieldSize range
dotsY = numpy.random.uniform(low=-fieldSize, high=fieldSize, size=(dotsN,))
dotsTheta = numpy.random.rand(dotsN) * 360 # array with shape (500,)
dotsRadius = numpy.random.rand(dotsN) * fieldSize
randDotsX = numpy.random.uniform(low=-fieldSize, high=fieldSize,size=(dotsN,))
randDotsY = numpy.random.uniform(low=-fieldSize, high=fieldSize,size=(dotsN,))
# initializing experiment stimuli
transDots = visual.ElementArrayStim(win, nElements=dotsN, sizes=elemSize, elementTex=None,
colors=(1.0, 1.0, 1.0), xys=random([dotsN, 2]) * fieldSize,
colorSpace='rgb', elementMask='circle', fieldSize=fieldSize)
rotDots = visual.ElementArrayStim(win, nElements=dotsN, sizes=elemSize, elementTex=None,
colors=(1.0, 1.0, 1.0), xys=random([dotsN, 2]),
colorSpace='rgb', elementMask='circle', texRes=128, fieldSize=fieldSize, )
fixation = visual.GratingStim(win, size=0.2, pos=[0,0], sf=0,color = 'red')
condList = ( ['rotClock', 'rotCounterClock'], ['radialIn', 'radialOut'],
['transUp','transDown'], ['transRight','transLeft'])
for trials in range(nTrials): #number of blocks
cond = choice(condList)
print cond
for condType in cond:
# assign parameters according to the condition
if condType == 'transUp' or condType == 'transRight' or condType == 'rotCounterClock' or condType == 'radialOut':
moveSign = 1 # positive for up and right movement
elif condType == 'transDown' or condType == 'transLeft' or condType == 'rotClock' or condType == 'radialIn':
moveSign = -1 # negative for down and left movement
#Frame Loop
for frameN in range(stimDur):
dieScoreArray = numpy.random.rand(dotsN) # generating array of float numbers
deathDots = (dieScoreArray < 0.01) #assigning True(death warrant) for numbers below 0.01
#handling each motion type individually
if condType == 'transUp':
dotsY = (dotsY + speed * moveSign)
transMove = True
transDots.setXYs(numpy.array([dotsX, dotsY]).transpose())
outfieldDots = (dotsY >= fieldSize)
dotsY[outfieldDots] = numpy.random.rand(sum(outfieldDots)) * fieldSize - fieldSize # out of field dots are replotted
dotsY[deathDots] = numpy.random.rand(sum(deathDots)) * (fieldSize + fieldSize) - fieldSize #death dots are replotted
elif condType == 'transDown':
dotsY = (dotsY + speed * moveSign)
transMove = True
transDots.setXYs(numpy.array([dotsX, dotsY]).transpose())
outfieldDots = (dotsY <= -fieldSize)
dotsY[outfieldDots] = numpy.random.rand(sum(outfieldDots)) * fieldSize
dotsY[deathDots] = numpy.random.rand(sum(deathDots)) * (fieldSize + fieldSize) - fieldSize
elif condType == 'transRight':
dotsX = (dotsX + speed * moveSign)
transMove = True
transDots.setXYs(numpy.array([dotsX, dotsY]).transpose())
outfieldDots = (dotsX >= fieldSize)
dotsX[outfieldDots] = numpy.random.rand(sum(outfieldDots)) * fieldSize - fieldSize
dotsX[deathDots] = numpy.random.rand(sum(deathDots)) * (fieldSize + fieldSize) - fieldSize
elif condType == 'transLeft':
dotsX = (dotsX + speed * moveSign)
transMove = True
transDots.setXYs(numpy.array([dotsX, dotsY]).transpose())
outfieldDots = (dotsX <= -fieldSize)
dotsX[outfieldDots] = numpy.random.rand(sum(outfieldDots)) * fieldSize
dotsX[deathDots] = numpy.random.rand(sum(deathDots)) * (fieldSize + fieldSize) - fieldSize
elif condType == 'radialIn':
dotsRadius = (dotsRadius + speed * moveSign)
transMove = False
outFieldRadius = (dotsRadius <= 0.03)
dotsRadius[outFieldRadius] = numpy.random.rand(sum(outFieldRadius)) * fieldSize
dotsRadius[deathDots] = numpy.random.rand(sum(deathDots)) * fieldSize
thetaX, radiusY = pol2cart(dotsTheta, dotsRadius)
rotDots.setXYs(numpy.array([thetaX, radiusY]).transpose())
elif condType == 'radialOut':
dotsRadius = (dotsRadius + speed * moveSign)
transMove = False
outFieldRadius = (dotsRadius >= fieldSize)
dotsRadius[outFieldRadius] = numpy.random.rand(sum(outFieldRadius))
dotsRadius[deathDots] = numpy.random.rand(sum(deathDots))
thetaX, radiusY = pol2cart(dotsTheta, dotsRadius)
rotDots.setXYs(numpy.array([thetaX, radiusY]).transpose())
elif condType == 'rotClock' or condType == 'rotCounterClock':
dotsTheta += speed * moveSign# clockwise or counterclocwise
transMove = False
dotsTheta[deathDots] = numpy.random.rand(sum(deathDots)) * 360
thetaX, radiusY = pol2cart(dotsTheta, dotsRadius)
rotDots.setXYs(numpy.array([thetaX, radiusY]).transpose())
#drawing stimuli
if transMove == True:
transDots.draw()
elif transMove == False:
rotDots.draw()
fixation.draw()
win.flip()
win.close()
core.quit()