Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Supported by

[open] Continuous Flash Supression Experiment.

edited October 2013 in OpenSesame

Hi guys,

I am programing an Continuous Flash Supression experiment (CFS).

The basic idea is to present on one eye an image (face or car or whatever) and on the other eye overlapping circular patches that are random in color and size and switching at around 13 Hz.
Here you can see to have an idea (Taken from Martin Hebart website).

I created an inline python script to present the flashing circles:


from psychopy.visual import GratingStim, event, core,SimpleImageStim,TextStim, Circle import numpy as np Sq_area= 250 circ_area=0 while circ_area<(8*(Sq_area*Sq_area)): myTex = np.random.random(3) Opac = np.random.uniform(0.3, 1, size=1) Posx = np.random.uniform(-(Sq_area/2), (Sq_area/2), size=1) Posy = np.random.uniform(-(Sq_area/2), (Sq_area/2), size=1) Rad = np.random.uniform(10, (Sq_area/5), size=1) myStim = Circle(win,units='pix', radius=Rad, opacity=Opac, pos=(Posx,Posy), lineWidth=0) myStim.setFillColor(myTex, 'rgb') myStim.setLineColor(myTex, 'rgb') myStim.draw() circ_area= circ_area + ((Rad*Rad)*np.pi) win.flip() core.wait(0.05)

Of course this is extremely inefficient and memory demanding, so it is impossible to get a reliable flashing rate, since the computer get stuck sometimes.

Does anybody has another more efficient idea how to do this?
Is the only other option to create several images (jpg) and load them randomly?

Thanks a lot in advance for any feedback.

Cheers,

Felipe

Comments

  • edited 2:21PM

    Hi,

    This seems an interesting problem.
    Without knowing much about psychophysics myself, I can only make some suggestions:

    • Do the stimuli really need to be generated freshly on each trial?
      If PsychoPy allows this, maybe you could instead generate a number of folders full of .png of .svg images using your script, and then use something like ImageMagick to convert each folder into a video? This would be pretty painless compared to showing a different 100 times a second.

      • Failing this, you may be able to generate a list of canvas objects (or possibly window, or win objects in PsychoPy terminology, I'm not sure) during the prepare phase of your trial, and then display them sequentially using something like
    # prepare phase
    
    list_of_frames = []
    
    for i in range(number_of_frames_needed):
        this_frame = canvas(exp) # Or this_frame = A_New_Psychopy_Window_Instance
        # Your inline script for generating frames here
        list_of_frames.append(this_frame)
    
    # run phase
    for frame in list_of_frames:
        frame.show()
        self.sleep(5)
    

    I hope this helps!

    Eoin

  • edited 2:21PM

    Thanks a lot for your answer Eoin,

    To add the needed frames in the prepare phase doesn't seems to really improve the situation.
    Still the refresh rate is too slow.

    For the moment i am thinking about 2 options.
    One is to load at the very beginning of the experiment something like 200 configurations of frames and choose randomly 36 on each trial (I need to present 3 secs at a sampling rate of 12 Hz).
    Another is to definitely create in JPG format something like 500 random pics pre-load them to be used during the experiment.

    Do you think any of them is better than the other? Any other idea?
    Thanks in advance to any creative mind there.

    Felipe

  • edited October 2013

    I've just tried the following, and it seems to do what you want on my computer anyway. Maybe you could try this, and let us know how you get on?

    I've made a new experiment, and in it I've placed a single inline_script item.
    In the Prepare Phase tab of this, I've typed:

    import os
    path = '/home/eoin/Pictures/Webcam/'
    # Change this to a folder on your computer containing about 35 images.
    
    images = []
    for img in os.listdir(path):
        image_path = exp.get_file(os.path.join(path, img))
        images.append(image_path)
    self.images = images
    

    Then, in the Run Phase tab, I've typed:

    from openexp.canvas import canvas
    my_canvas = canvas(exp)
    
    for fpath in self.images:
        my_canvas.clear()
        my_canvas.image(fpath)
        my_canvas.show()
        exp.sleep(83) # 12Hz = 83ms between frames
    

    The result for me is a 3 second burst of all 35 images in my Webcam folder.

    If this works on your machine, I would advise simply generating your stimuli as a series of jpgs, saving them to one folder, and then modifying my code so that the prepare phase looks like:

    import os, random
    path = '/home/eoin/Pictures/Webcam/'
    # Change this to a folder on your computer containing about 35 images.
    
    images = []
    # Randomize the stimuli, and pick the first 35.
    list_of_filenames = random.shuffle(os.listdir(path))
    for i in range(35):
        filename = list_of_filenames[i]
        image_path = exp.get_file(os.path.join(path, filename))
        images.append(image_path)
    self.images = images
    

    Edit:
    I've just tried this on a different folder of images, with a higher resolution (2048x1536, from my phone, rather than 640x480, from my webcam), and I do find it lags. You may want to compress your jpgs (again, ImageMagick is your friend here).

    Edit Again:
    For a good laugh, set your image path to a folder of FaceGen stimuli.

  • edited 2:21PM

    Hi Eoin,

    Thanks a lot again for your help.
    Actually my original idea was trying to generate images on the fly but it seems that any method is definitely too inefficient, since requires the generation of multiple canvas.
    As you proposed i am at the moment creating a pool of 300 images and loading 36 randomly on every trial, it seem to work pretty well.
    I need pictures that are 300*300 px. so there is not any kind of memory overload.

    Thanks again for your advice and help.

    Best,

    Felipe

  • edited November 2013

    Hi There again... This is maybe a really silly question but I 've been stuck on it for some hours and i cant find a proper solution. In the CFS experiment I have succesfully overcome the problem of multiple pictures presentation thanks to Eoin's idea.
    Nevertheless it is impossible for me to present 2 canvas at the same time (i need to present the flashing mondrian pictures at the same time that a face that is presented during the same period of time). So the code I have so far is:

    Prepare phase:

    import os, random
    path = '/Users/aedo-jury/Documents/FELIPE/Awareness Faces/Experiment /masks'
    # this is the folder on containing mondrian images for the flashing canvas.
    
    images = []
    # Randomize the stimuli, and pick the first 35.
    list_of_filenames = (os.listdir(path))
    random.shuffle(list_of_filenames)
    
    for i in range(24):
        filename = list_of_filenames[i]
        image_path = exp.get_file(os.path.join(path, filename))
        images.append(image_path)
    self.images = images
    
    # Path to the folder containg the faces
    banana=('/Users/aedo-jury/Documents/FELIPE/Awareness Faces/Experiment /pics/{0}.png'.format(picture))
    

    Run Phae: Here comes the tricky thing becasue If i "put my_canvas2.show()" before or after the canvas for the flashing mondrians it will present them before or after and not at the same time. Contrary if i put it inside of the mondrian loop it will flash the pictures.

    from openexp.canvas import canvas
    from psychopy.visual  import GratingStim, event, core,SimpleImageStim,TextStim,  Circle
    
    # im=SimpleImageStim(win,banana, flipHoriz=False, pos=(-400,200), units='pix')
    
    
    my_canvas = canvas(exp)
    my_canvas2 = canvas(exp)
    my_canvas2.image(banana,x=800, y=600, scale=0.5)
    
    
    for fpath in self.images:
        my_canvas.clear()
        my_canvas.image(fpath,x=200, y=200, scale=0.5)
        my_canvas.show()
        my_canvas.set_penwidth(30)
        exp.sleep(83) # 12Hz = 83ms between frames
    
    my_canvas2.show()
    exp.sleep(2000)
    

    Any idea?

    Thanks in advance.

    Felipe

  • edited 2:21PM

    Hi,

    Could you please clarify, are you trying to superimpose the flashing mondrians on top of your static image (the banana, I think), rather than alternating between the two, or showing them side by side?

    If so, I don't think it's possible to superimpose two canvasses in OpenSesame like this. What you could do instead is create .png images where this is already done - i.e. for each target image you want to present, generate a folder of images of it superimposed with each mondrain in advance, and then show the images from each folder, using the code above.

    While this isn't something I've specifically done myself, it should be relatively easy using ImageMagick, especially if you ask on the forums dedicated to the software.

    Not having ImageMagick installed on my office computer, I can only give an untested example, but I think that to superimpose 100 mondrain images, in this case titled mondrain001.png to mondrain100.png, over a target titled target.png in the same folder, a DOS/Unix command along these lines would be appropriate.

    composite -blend 50 target.png mondrain*.png target*.png
    

    creating files titled target001.png to target100.png.

    Eoin

  • edited 2:21PM

    Hi Eoin,

    Thanks for your reply.
    Sorry I wasnt so clear.

    Actually what I need is to present continuously one picture during 3 secs on one side of the screen (banana) while on the other side of the screen at the same time are flickering the mondrian paterns at 12 hz (the loop canvas).

    I hope now is a bit clearer.

    Thanks a lot,

    Felipe

  • edited 2:21PM

    Ah, ok, that's a lot simpler.
    A Canvas refers to the whole screen, you can't have two canvases side by side, but you can easily draw your mondrains on one side of the canvas, and the target on the other.

    I think the most efficient way of doing this would be to prepare 24(?) canvases like this in advance during the prepare phase:
    canvases

    import os, random
    from openexp.canvas import canvas
    
    path = '/Users/aedo-jury/Documents/FELIPE/Awareness Faces/Experiment /masks'
    # this is the folder on containing mondrian images for the flashing canvas.
    
    # Get the target
    picture = exp.get('picture') # Get the Experiment variable
    banana=('/Users/aedo-jury/Documents/FELIPE/Awareness Faces/Experiment /pics/{0}.png'.format(picture))
    
    # Randomize the mondrains, and pick the first n_of_frames.
    n_of_frames = 24 # Use 24 mondrains
    list_of_filenames = (os.listdir(path))
    random.shuffle(list_of_filenames)
    
    canvases = [] # A list of canvases to show sequentially.
    for i in range(n_of_frames):
        this_canvas = canvas(exp)
        # Get the mondrain and add it to the canvas
        filename = list_of_filenames[i]
        image_path = exp.get_file(os.path.join(path, filename))
        my_canvas.image(image_path, x=200, y=200, scale=0.5)
        # Add the target to the same canvas
        this_canvas.image(banana,x=800, y=600, scale=0.5)
        # Add our canvas to the list
        canvases.append(this_canvas)
    self.canvases= canvases
    

    Then, in the run phase, all you need to do is show this list of canvases sequentially.

    # Show each canvas for 83ms.
    for canvas in self.canvases:
        canvas.show()
        exp.sleep(83) # 12Hz = 83ms between frames
    
    # Clear screen (uncomment to use)
    #canvas.clear()
    #canvas.show()
    
    # Wait two seconds after last frame
    exp.sleep(2000)
    

    I can't test this from this computer, but hopefully this should solve your (interesting!) problem.

    Eoin

Sign In or Register to comment.