Speeding up (vectorising?) a for loop
We are developing a dynamic visual search experiment, where a number of dots move randomly around the screen. The code involves a series of for loops (an extract from the code is pasted in below). Our issue is that as NStim increases, the time taken to execute the for loops increases, meaning that the dots are moving slower when there are more of them. Is it possible to vectorise the code in order to avoid this problem? (sorry, we have some experience with Matlab but not with Python). We'd really like the dots to move at the same speed!
Thanks!
# Loop through all frames
for j in range(NFrames):
# For each frame, clear the canvas and then loop through all stimuli
myCanvas.clear()
for i in range(NStim):
# Get the stimulus properties
x, y, a, v, r = stimList[i]
# Update the position of the stimulus based on the angle and the speed
x += v * math.cos(a)
y += v * math.sin(a)
# If the stimulus leaves the screen, reverse direction by 180 deg (= 1pi radial)
if x <= 0 or x >= self.get('width') or y <= 0 or y >= self.get('height'):
a = a + math.pi
else:
# else randomly rotate the stimulus a bit
a += (random.random()-.5) * maxRotSpeed
# Highlight the targets on the first frame
if i < NTarget and j == 0:
color = targetColor
else:
color = normalColor
# Draw the stimulus
myCanvas.circle(x, y, r, fill=True, color=color)
# Store the new stimulus properties back in the stimulus list
stimList[i] = x, y, a, v, r
# Show the canvas
myCanvas.show()
# Sleep after the first frame so that the participant can identify the targets
if j == 0:
self.sleep(firstFrameDur)
# Store the coordinates of the stimuli in the last frame, in order to compare
# the mouse click responses with the actual positions
Comments
Hi,
Rendering the stimuli like this is not optimal, but in most cases it should be fast enough. What I think might be going on is that you're using the xpyriment back-end, and have not set the
auto_prepare
keyword toFalse
when creatingcanvas
objects (it'sTrue
by default). Whenauto_prepare
isTrue
the canvas will be prepared for being flipped to the display after every drawing operation, which takes a bit of time. If you set it toFalse
, drawing will go much faster, but you have to explicitly callcanvas.prepare()
. This is illustrated in the example:This, by the way, is currently specific to the xpyriment backend.
Does this help? If not, there are plenty of other ways to speed up rendering.
Cheers,
Sebastiaan
Check out SigmundAI.eu for our OpenSesame AI assistant!
Hi Sebastiaan,
thanks for your reply! We're actually not using xpyriment backend (I just ran it using xpyriment and it was REALLY slow). It is much faster/smoother in pyscho & legacy, but there is still a slight speed difference between the Nstim sizes (i.e. 5 dots move quicker than >5 dots), which isn't ideal.
Thanks,
Khia
In that case, it's probably best to really implement this properly, using PsychoPy, which allows you to update stimuli on the fly. So you don't need to clear the canvas and redraw everything from scratch, but rather simply change the position of stimuli. This is much faster, so you should be able to draw as many stimuli as you want.
Below you see an example script that does more or less what you need. You can just copy-paste it into an
inline_script
. I also wrapped the moving dot into a nice class, so that the code remains clean. But I don't think you need any real knowledge of object-oriented programming to use this.Does this get you started?
Check out SigmundAI.eu for our OpenSesame AI assistant!
That's great thank you Sebastiaan!
Seeing as you have been so helpful, do you happen to know if/how I can interrupt the trial before nframe runs to its end? So nframe would be the maximum run length of a trial before time-out but the trial could be halted at any point before that by moving the mouse and having the cursor appear on the screen.
I would like to be able to move the cursor in the trial window before the max nframe so I can select a target (that is then recorded with the data logger before a new trial begins).
Many thanks,
Khia