The Code Component can be used to insert short pieces of python code into your experiments. This might be create a variable that you want for another Component, to manipulate images before displaying them, to interact with hardware for which there isn’t yet a pre-packaged component in PsychoPy (e.g. writing code to interact with the serial/parallel ports). See code uses below.
Be aware that the code for each of the components in your Routine are executed in the order they appear on the Routine display (from top to bottom). If you want your Code Component to alter a variable to be used by another component immediately, then it needs to be above that component in the view. You may want the code not to take effect until next frame however, in which case put it at the bottom of the Routine. You can move Components up and down the Routine by right-clicking on their icons.
Clockassociated with them, which gets reset at the beginning of that repeat of the routine. So if you have a Routine called trial, there will be a
Clockcalled trialClock and so you can get the time (in sec) from the beginning of the trial by using::
currentT = trialClock.getTime()
To see what other variables you might want to use, and also what terms you need to avoid in your chunks of code, compile your script before inserting the code object and take a look at the contents of that script.
Note that this page is concerned with Code Components specifically, and not all cases in which you might use python syntax within the Builder. It is also possible to put code into a non-code input field (such as the duration or text of a Text Component). The syntax there is slightly different (requiring a $ to trigger the special handling, or \$ to avoid triggering special handling). The syntax to use within a Code Component is always regular python syntax.
The parameters of the Code Component simply specify the code that will get executed at 5 different points within the experiment. You can use as many or as few of these as you need for any Code Component:
- Before Experiment:
Things that need to be done just once, like importing a supporting module, which do not need the experiment window to exist yet.
- Begin Experiment:
Things that need to be done just once, like initialising a variable for later use, which may need to refer to the experiment window.
- Begin Routine:
Certain things might need to be done just once at the start of a Routine e.g. at the beginning of each trial you might decide which side a stimulus will appear
- Each Frame:
Things that need to updated constantly, throughout the experiment. Note that these will be executed exactly once per video frame (on the order of every 10ms), to give dynamic displays. Static displays do not need to be updated every frame.
- End Routine:
At the end of the Routine (e.g. the trial) you may need to do additional things, like checking if the participant got the right answer
- End Experiment:
Use this for things like saving data to disk, presenting a graph(?), or resetting hardware to its original state.
There are many ways to do this, but you could add the following to the Begin Routine section of a Code Component at the top of your Routine. Then set your stimulus position to be $targetPos and set the correct answer field of a Keyboard Component to be $corrAns (set both of these to update on every repeat of the Routine).:
if random()>0.5: targetPos=[-2.0, 0.0]#on the left corrAns='left' else: targetPos=[+2.0, 0.0]#on the right corrAns='right'
As with the above there are many different ways to create noise, but a simple method would be to add the following to the Begin Routine section of a Code Component at the top of your Routine. Then set the image as $noiseTexture.:
noiseTexture = random.rand((128,128)) * 2.0 - 1
Make a new routine, and place it at the end of the flow (i.e., the end of the experiment). Create a Code Component with this in the Begin Experiment field:
expClock = core.Clock()
and put this in the Begin routine field:
msg = "Thanks for participating - that took %.2f minutes in total" %(expClock.getTime()/60.0)
Next, add a Text Component to the routine, and set the text to $msg. Be sure that the text field’s updating is set to “Set every repeat” (and not “Constant”).
Code components can also be used to control the end of a loop. See examples in Recipes:builderTerminateLoops.
The most complete way to find this out for your particular script is to compile it and take a look at what’s in there. Below are some options that appear in nearly all scripts. Remember that those variables are Python objects and can have attributes of their own. You can find out about those attributes using:
Common PsychoPy variables:
expInfo: This is a Python Dictionary containing the information from the starting dialog box. e.g. That generally includes the ‘participant’ identifier. You can access that in your experiment using exp[‘participant’]
t: the current time (in seconds) measured from the start of this Routine
frameN: the number of /completed/ frames since the start of the Routine (=0 in the first frame)
Windowthat the experiment is using
Your own variables:
anything you’ve created in a Code Component is available for the rest of the script. (Sometimes you might need to define it at the beginning of the experiment, so that it will be available throughout.)
the name of any other stimulus or the parameters from your file also exist as variables.
most Components have a status attribute, which is useful to determine whether a stimulus has NOT_STARTED, STARTED or FINISHED. For example, to play a tone at the end of a Movie Component (of unknown duration) you could set start of your tone to have the ‘condition’myMovieName.status==FINISHED
Selected contents of the numpy library and numpy.random are imported by default. The entire numpy library is imported as np, so you can use a several hundred maths functions by prepending things with ‘np.’:
sin(), cos(), tan(), and pi: For geometry and trig. By default angles are in radians, if you want the cosine of an angle specified in degrees use cos(angle*180/pi), or use numpy’s conversion functions, rad2deg(angle) and deg2rad(angle).
linspace(): Create an array of linearly spaced values.
log(), log10(): The natural and base-10 log functions, respectively. (It is a lowercase-L in log).
sum(), len(): For the sum and length of a list or array. To find an average, it is better to use average() (due to the potential for integer division issues with sum()/len() ).
average(), sqrt(), std(): For average (mean), square root, and standard deviation, respectively. Note: Be sure that the numpy standard deviation formula is the one you want!
np.______: Many math-related features are available through the complete numpy libraries, which are available within psychopy builder scripts as ‘np.’. For example, you could use np.hanning(3) or np.random.poisson(10, 10) in a code component.