I am working on a Psychopy programm on a windows machine which presents similar stimuli in a row. So, the programm reads in a text file with some parameters about the shape of the stimulus (e.g. rectangle-shaped stripe with 10 degrees width at 90 degrees orientation) or the stimulus color and timing. I use the ShapeStim class for the stripes. The approx.10-20 different stripes should then be presented subsequently.
All of this works, but I have some timing issues. When finishing a presentation of a stripe and a new stripe is generated, the parameters are modified and then presented in the opened window. This takes about 30 ms of delay and this should not happen in a usual experimental flow.
I read the advices for better timing, so then I did not create a new ShapeStim for every stripe, instead I reused the old one and just modified the parameters. But this still caused the 3-5 ms delay.
So I tried doing Threading, instead of reusing the ShapeStim object. In a thread I prepare the next stripe while the current stripe is being presented (this usually takes 2-4 seconds, so there is plenty of time)
This is within my main() function:
def main(): # do a lot of initializing stuff, getting data aquisition started .... ... if FIRST: stripe = CylinderStripe(window,stripe_attributes,stripe_number) First = False else: stripe = next_stripe.get() # Threading, set the next stripes parameter within __init__ of class 'CylinderStripe' pool = ThreadPool(processes = 1) next_number = (stripe_number+1) % stripes_no next_stripe = pool.apply_async(CylinderStripe, (window,stripe_attributes,next_number)) # Draw the current stripe output_data = stripe.draw(global_clock)
There is a module called CylinderStripe which sets the stripe attributes in it’s init function:
import helper class CylinderStripe(object): def __init__(self,window, stripe_attributes, stripe_number): # The same for all classes self.win = window self.number = stripe_number self.attributes = stripe_attributes self.win.color = helper.set_color(self.attributes.COLOR) self.rect = visual.ShapeStim(self.win, units='',fillColorSpace='rgb', lineWidth=0) # stripe attributes self.rect.vertices = self.attributes.vertices self.rect.pos = (self.attributes.xpos, self.attributes.ypos) self.rect.fillColor = helper.set_fgcol(self.attributes.FGCOLOR) self.rect.ori = self.attributes.orientation # set timing self.min_duration = self.attributes.min_duration self.duration = self.attributes.duration def draw(self,global_clock): # As long as duration, draw the stimulus for frameN in range(int(self.duration*FRAMERATE)): # Move Stimulus for a certain time if self.attributes.xvelocity != 0 and global_clock.getTime() <= self.min_duration: self.rect.pos += (self.attributes.xvelocity,0) # Finally, present stimulus self.rect.draw() # process some information for output_data self.win.flip() return output_data
But with this technique there is about 20 ms delay. I am confused, because I thought that threading could cure my problem via parallelization. Do I do something wrong ? I havent applied threading or multiprocessing before. Or maybe there is another idea to speed up the creation of another stripe ?
Thank you in advance!