Re: [psychopy-users] Does PsychoPy allow image "fade in - fade out" transitions?

656 views
Skip to first unread message

Jeremy Gray

unread,
May 10, 2013, 9:07:17 PM5/10/13
to psychop...@googlegroups.com
Hi Steve,

This is certainly possible, by setting the image opacity dynamically. Start it at 0.0 and increase to 1.0 over your rise-time window, hold, then ramp it back down. In the builder you'd need to calculate an opacity value as a function of time (or visual frame) in a code component, and then set the opacity to that value on every frame.

--Jeremy



On Fri, May 10, 2013 at 8:44 PM, Steve H. <stavros.ha...@gmail.com> wrote:
Hello,

I'd like to set up an experiment in which random images will be flickered on the screen for 2 seconds and the participant will have to identify them.

Now, the issue that I try to avoid here is having the image appear immediately, that is, "flashing" on the screen. 

Ideally, I'd like to have the trial start with a black screen, then have the first stimulus appear gradually ("fade in" from black), stay on the screen for 2 seconds and then "fade out" to black.

Is this possible to do with PsychoPy? 

My apologies if I'm too vague here, let me know if you need me to explain this better and thank you in advance.

SH

--
You received this message because you are subscribed to the Google Groups "psychopy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to psychopy-user...@googlegroups.com.
To post to this group, send email to psychop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/psychopy-users/-/UAjqIcVoD6MJ.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Steve H.

unread,
May 10, 2013, 10:35:04 PM5/10/13
to psychop...@googlegroups.com
Thank you for the prompt reply Jeremy. In the builder, I would have to set 3 functions separate by commas in the opacity box?

Greatly appreciated.

Stavros

Michael MacAskill

unread,
May 10, 2013, 11:45:42 PM5/10/13
to psychop...@googlegroups.com

On 11 May, 2013, at 14:35, Steve H. <stavros.ha...@gmail.com> wrote:

> Thank you for the prompt reply Jeremy. In the builder, I would have to set 3 functions separate by commas in the opacity box?

No: in the opacity box just put a single variable name, say, 'alpha' (without the quotes), and select "set every frame".

The value of alpha will be set by code in the "each frame" box of a Code component. e.g. if you want it to fade in and out over 0.5 s and be displayed at full opacity for 2 s in between, here is some untested code:

if t < 0.5:
alpha = t / 0.5 # ramp from 0 at the beginning, 1.0 at the end
elif t > 2.0:
alpha = 1.0 - ((t-2.5) / 0.5) # ramp down from 1 to 0
else:
alpha = 1.0 # must be in the middle 2s period

The Code component should appear above the stimulus in the Builder GUI so that the alpha value is calculated before the stimulus is drawn on each frame.


Cheers,

Michael

Michael MacAskill

unread,
May 10, 2013, 11:51:15 PM5/10/13
to psychop...@googlegroups.com

On 11 May, 2013, at 15:45, Michael MacAskill <michael....@otago.ac.nz> wrote:

> elif t > 2.0:

Oops, that should actually be "t > 2.5" in that particular example.


Steve H.

unread,
May 11, 2013, 2:10:52 AM5/11/13
to psychop...@googlegroups.com
Works like a charm Mike! 

Thank you both for the prompt replies. This has solved the issue and I'll post the code once the experiment has been set up.

Thanks again!

Jeremy Gray

unread,
May 11, 2013, 7:33:34 AM5/11/13
to psychop...@googlegroups.com
In the Builder, in an image's Opacity box, put a new variable name "fader" (but without the quotes), and set it to update every frame. In the Stop (duration) box, put "$img_dur" (no quotes) Then add a new code component to the routine. In the Begin routine box, put 

fader = 0  # starting opacity, 0 = transparent
img_dur = 2  # total display time for the image
fade_over = 0.5  # how long a full fade-in/out should take
f_clock = core.Clock()

And in the Each frame box put this:

f = f_clock()
if f < fade_over:
  fader = f / fade_over
else:
  fader = min(1, (img_dur-f)/fade_over)

This will give you a linear ramp in/out. Other forms are possible, just change the math each frame.

--Jeremy



--
You received this message because you are subscribed to the Google Groups "psychopy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to psychopy-user...@googlegroups.com.
To post to this group, send email to psychop...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msg/psychopy-users/-/KL5Kb-Yr8vEJ.

Jeremy Gray

unread,
May 11, 2013, 7:37:46 AM5/11/13
to psychop...@googlegroups.com
dop! now I just saw Mike's excellent answer.

Steve H.

unread,
May 11, 2013, 1:36:19 PM5/11/13
to psychop...@googlegroups.com
Hi Jeremy, thanks for the input.

I'm getting the following error when I try to run it:

"f= f_clock()

AttributeError: Clock instance has no __call__ method"

Here's the script (created by Builder):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This experiment was created using PsychoPy2 Experiment Builder (v1.76.00), May 11, 2013, at 13:32
If you publish work using this script please cite the relevant PsychoPy publications
  Peirce, JW (2007) PsychoPy - Psychophysics software in Python. Journal of Neuroscience Methods, 162(1-2), 8-13.
  Peirce, JW (2009) Generating stimuli for neuroscience using PsychoPy. Frontiers in Neuroinformatics, 2:10. doi: 10.3389/neuro.11.010.2008
"""

from __future__ import division  # so that 1/3=0.333 instead of 1/3=0
from psychopy import visual, core, data, event, logging, gui
from psychopy.constants import *  # things like STARTED, FINISHED
import numpy as np  # 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

# Store info about the experiment session
expName = u'Blur (alternative code)'  # from the Builder filename that created this script
expInfo = {'participant':'', 'session':'001'}
dlg = gui.DlgFromDict(dictionary=expInfo, title=expName)
if dlg.OK == False: core.quit()  # user pressed cancel
expInfo['date'] = data.getDateStr()  # add a simple timestamp
expInfo['expName'] = expName

# Setup files for saving
if not os.path.isdir('data'):
    os.makedirs('data')  # if this fails (e.g. permissions) we will get error
filename = 'data' + os.path.sep + '%s_%s' %(expInfo['participant'], expInfo['date'])
logFile = logging.LogFile(filename+'.log', level=logging.EXP)
logging.console.setLevel(logging.WARNING)  # this outputs to the screen, not a file

# An ExperimentHandler isn't essential but helps with data saving
thisExp = data.ExperimentHandler(name=expName, version='',
    extraInfo=expInfo, runtimeInfo=None,
    originPath=None,
    savePickle=True, saveWideText=True,
    dataFileName=filename)

# Setup the Window
win = visual.Window(size=(1920, 1080), fullscr=True, screen=0, allowGUI=False, allowStencil=False,
    monitor='testMonitor', color=[0,0,0], colorSpace='rgb')

# Initialize components for Routine "trial"
trialClock = core.Clock()
image = visual.ImageStim(win=win, name='image',
    image=u'D:\\Artist Perception\\Artist Perception\\New Stimuli\\Cropped Test Stimuli\\CroppedBat11.bmp', mask=None,
    ori=0, pos=[0, 0], size=[0.5, 0.5],
    color=[1,1,1], colorSpace=u'rgb', opacity=1.0,
    texRes=128, interpolate=False, depth=0.0)


# Create some handy timers
globalClock = core.Clock()  # to track the time since experiment started
routineTimer = core.CountdownTimer()  # to track time remaining of each (non-slip) routine 

#------Prepare to start Routine "trial"-------
t = 0
trialClock.reset()  # clock 
frameN = -1
# update component parameters for each repeat
fader = 0  # starting opacity, 0 = transparent
img_dur = 2  # total display time for the image
fade_over = 0.5  # how long a full fade-in/out should take
f_clock = core.Clock()
# keep track of which components have finished
trialComponents = []
trialComponents.append(image)
for thisComponent in trialComponents:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

#-------Start Routine "trial"-------
continueRoutine = True
while continueRoutine:
    # get current time
    t = trialClock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *image* updates
    if t >= 0.0 and image.status == NOT_STARTED:
        # keep track of start time/frame for later
        image.tStart = t  # underestimates by a little under one frame
        image.frameNStart = frameN  # exact frame index
        image.setAutoDraw(True)
    elif image.status == STARTED and t >= (0.0 + img_dur):
        image.setAutoDraw(False)
    if image.status == STARTED:  # only update if being drawn
        image.setOpacity(fader, log=False)
    f = f_clock()
    if f < fade_over:
      fader = f / fade_over
    else:
      fader = min(1, (img_dur-f)/fade_over)
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested that we end
        routineTimer.reset()  # this is the new t0 for non-slip Routines
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in trialComponents:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the [Esc] key)
    if event.getKeys(["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()

#-------Ending Routine "trial"-------
for thisComponent in trialComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)


win.close()
core.quit()



This is the machine I use for the program:

Win 8 Pro x64

PCPartPicker part list: http://pcpartpicker.com/p/blx1
Price breakdown by merchant: http://pcpartpicker.com/p/blx1/by_merchant/

CPU: Intel Core i5-3570K 3.4GHz Quad-Core Processor  ($189.99 @ Microcenter) 
CPU Cooler: Cooler Master Hyper 212 EVO 82.9 CFM Sleeve Bearing CPU Cooler  ($24.99 @ Newegg) 
Motherboard: ASRock Z68 Extreme3 Gen3 ATX  LGA1155 Motherboard 
Memory: G.Skill Ripjaws X Series 16GB (4 x 4GB) DDR3-1866 Memory  ($139.99 @ Newegg) 
Storage: Corsair Force Series GT 120GB 2.5" Solid State Disk  ($129.99 @ Newegg) 
Storage: Seagate Barracuda ES 750GB 3.5" 7200RPM Internal Hard Drive 
Video Card: EVGA GeForce GTX 670 2GB Video Card  ($369.99 @ NCIX US) 
Case: Cooler Master Storm Scout ATX Mid Tower Case  ($54.99 @ Newegg) 
Power Supply: Antec EarthWatts Green 650W 80 PLUS Bronze Certified ATX12V Power Supply  ($77.99 @ Adorama) 
Optical Drive: Asus DRW-24B1ST/BLK/B/AS DVD/CD Writer  ($16.99 @ Newegg) 
Total: $1004.92
(Prices include shipping, taxes, and discounts when available.)
(Generated by PCPartPicker 2013-05-11 13:35 EDT-0400)

Best,
Steven

Jeremy Gray

unread,
May 11, 2013, 5:00:42 PM5/11/13
to psychop...@googlegroups.com, psychop...@googlegroups.com
Oops typo on my part. Should be:
f=f_clock.getTime()


/* sent from a phone; pls forgive typo & brevity */ 
To view this discussion on the web visit https://groups.google.com/d/msg/psychopy-users/-/QTJWjBGUU5cJ.

SH

unread,
May 12, 2013, 3:07:30 AM5/12/13
to psychop...@googlegroups.com
Thank you, Jeremy- confirmed, works on my end. 

Sorry to be a pest, but would it be possible to both ramp on-maintain-ramp off an image and flicker it at the same time?

Many thanks once again.

SH

Jonas Lindeløv

unread,
May 12, 2013, 7:47:54 AM5/12/13
to psychop...@googlegroups.com
Yes, the flicker part is simply achieved by only drawing stimulus on some of the frames. But if the flicker is going to be fast, you probably want to time the presentation to monitor frames instead of continuous time as it is in Michaels example.

So if you want, say, 3 frames (50 ms on a 60 Hz monitor) stimulus and 3 frames black, you would do something like:

# Initiate stimuli etc.
from __future__ import division
from psychopy import visual
win = visual.Window()
stim = visual.TextStim(win)

# General version
fadeIn = 30  # Duration of fadein in frames
fadeOut = 30  # Duration of fadeout in frames
maintain = 120  # Duration of maintenance in frames
flickerInterval = 3  # Duration of on and off duration (3 --> 6 frames per cycle)

for frame in range(fadeIn + fadeOut + maintain):
    if frame < fadeIn:
        alpha = frame / fadeIn  # ramp up
    if frame > fadeIn + maintain:
        alpha = 1.0 - ((frame - fadeIn - maintain) / fadeOut)  # ramp down
    else:
        alpha = 1.0  # Maintain
    
    # Draw only on certain frames
    if frame / flickerInterval % 2 < 1:
        stim.setOpacity(alpha)
        stim.draw()
    win.flip()



If the variables are confusing, here is the same code with fewer variables:
# .... or version with numbers instead of variables
for frame in range(180):
    if frame < 30:
        alpha = frame / 30  # ramp up
    if frame > 150:
        alpha = 1.0 - ((frame - 150) / 30)  # ramp down
    else:
        alpha = 1.0  # Maintain
    
    # Draw only on certain frames
    if frame / 3 % 2 < 1:
        stim.setOpacity(alpha)
        stim.draw()
    win.flip()

The flicker-line with the % might be a bit confusing. It uses modulus and the output is like this for flickerInterval = 3:

for frame in range(20):
   print frame, frame / flickerInterval % 2 < 1 
0 True
1 True
2 True
3 False
4 False
5 False
6 True
7 True
8 True
9 False
10 False
11 False
12 True
13 True
14 True
15 False
16 False
17 False
18 True
19 True

... meaning "three frames on, then three frames off, then three frames on" etc.

Best,
Jonas

SH

unread,
May 12, 2013, 1:17:45 PM5/12/13
to psychop...@googlegroups.com
Hi Jonas, thank you for your contribution.

I'm testing your code now and I get this error with either 'numbers' or 'variables' versions:

image.setOpacity(alpha, log=False)
NameError = 'alpha' is not defined

I pasted the code exactly as is here.

All the best,
SH

Michael MacAskill

unread,
May 13, 2013, 12:36:24 AM5/13/13
to psychop...@googlegroups.com

On 13 May, 2013, at 05:17, SH <stavros.ha...@gmail.com> wrote:

> Hi Jonas, thank you for your contribution.
>
> I'm testing your code now and I get this error with either 'numbers' or 'variables' versions:
>
> image.setOpacity(alpha, log=False)
> NameError = 'alpha' is not defined
>
> I pasted the code exactly as is here.

Jonas' code is written as an example for the Coder view: it contains the entire drawing loop. It would take some modification to work within a Code component of the Builder (which I think you are using?) as Builder maintains its own drawing loop.

Mike
Message has been deleted

SH

unread,
May 16, 2013, 5:57:39 AM5/16/13
to psychop...@googlegroups.com
Hello once again. I've been trying to get flicker to work in builder using different types of script based on Jonas's but I can't seem to get it right. The code that I'm attaching here does exactly what I want in terms of stimuli presentation except from lack of flickering. 

I have tried googling flickering in python but haven't found a source of information yet. What would be the best way to start learning on how to add flickering to a script in Builder?

Thank you,
SH
Blur (laptop code).py

Andrew Poppe

unread,
May 16, 2013, 8:53:16 AM5/16/13
to psychop...@googlegroups.com
Hi SH,

attached are a builder script that produces flickering on my machine and the picture I was using. 
Hope that helps.

Andrew






--
You received this message because you are subscribed to the Google Groups "psychopy-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to psychopy-user...@googlegroups.com.
To post to this group, send email to psychop...@googlegroups.com.
picture_flicker.psyexp
laurelaitken.png

SH

unread,
May 16, 2013, 3:47:25 PM5/16/13
to psychop...@googlegroups.com
Hi Andrew,

Thank you, greatly appreciated. I'm working on this right now.

Firstly, this is what the presentation looks like:

Ramp On -> Hold - Ramp Off

just by copying the following lines to enable flickering, this is what happens 

Flicker Ramp On -> Hold (no flickering) -> Flicker Ramp Off

Code:
if (frameN//3) % 2 == 0:
    image.draw()

I'm working on this part now to allow flickering to occur during the whole presentation.

All the best,
SH 

Jonathan Peirce

unread,
May 28, 2013, 6:13:28 AM5/28/13
to psychop...@googlegroups.com
You can set the contrast and/or opacity to any value you like at any time. But psychopy doesn't have built-in methods to control these - you'd have to write your own code to handle custom on/off transitions.

Jon

For more options, visit https://groups.google.com/groups/opt_out.
 
 

-- 
Jonathan Peirce
Nottingham Visual Neuroscience

http://www.peirce.org.uk

This message and any attachment are intended solely for the addressee and may contain confidential information. If you have received this message in error, please send it back to me, and immediately delete it.   Please do not use, copy or disclose the information contained in this message or in any attachment.  Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham.

This message has been checked for viruses but the contents of an attachment may still contain software viruses which could damage your computer system, you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation.


SH

unread,
Jun 2, 2013, 7:15:58 PM6/2/13
to psychop...@googlegroups.com
Hi Jon,

Yes, I've been studying Python on the side ("A byte of Python") so I can write my own code for this. 

So far I had no luck with what I want to do though. It seems the "hold" command for opacity is not allowing to have flickering taking place at the same time.

Will keep at it.

Best,
SH
Reply all
Reply to author
Forward
0 new messages