{{:kpnl:psychopydocbanner2.png?200|}} \\
[[http://www.psychopy.org/index.html|PsychoPy website]] \\
PsychoPy is an open-source application to allow the presentation of stimuli and collection of data for a wide range of neuroscience, psychology and psychophysics experiments. It’s a free, powerful alternative to Presentation™ or e-Prime™, written in Python (a free alternative to Matlab™ ).
I have chosen PsychoPy as the primary stimulus presentation software for the lab for a number of reasons:
- It is free
- It is open-source
- Experiments can be developed in two environments
- ''Builder'' a nice GUI interface for quick and easy development of experiments
- ''Coder'' a programming environment for exploiting the power of Python programming to develop more complex paradigms and/or for greater customization an experiment.
- There is an active and friendly [[https://groups.google.com/forum/#!forum/psychopy-users|user group]] for getting help and addressing issues.
Below are notes and tips for building experiments for use in the EEG lab. Many of these tips include using a [[http://www.psychopy.org/builder/components/code.html|custom code componet]] in ''Builder''. This is a way of inserting short pieces of Python code into your Builder experiment. In other words, you can leverage some of the power of ''Coder'' without leaving the ''Builder'' GUI environment. An alternative would be to start by building your experiment in ''Builder'' and then compiling the code to be further modified in ''Coder''.
Moving between ''Builder'' and ''Coder'' is a one-way street. You can move from ''Builder'' to ''Coder'', but not from ''Coder'' to ''Builder''.
====== Tutorials ======
[[https://www.youtube.com/watch?v=9BqRyut2UZk|PsychoPy Tutorials]]
====== Miscellaneous Tips ======
* Do not use "filename" as a variable (i.e., column header in Excel). This conflicts with a variable in PsychPy and will result in some strange names for your output files.
* There are likely other variable names to avoid, but this is the first I've come across
====== Sending digital event codes ======
It is critical that we acquire stimulus-locked digital codes so that we can bin the data according to stimulus type during analysis. This is also essential for creating event-related averages of psychophysiological data (e.g. creating ERPs from EEG data) as it gives us the precise onset time of each stimulus. Below is a description of the hardware, software, and steps necessary for sending and acquiring such codes with PsychoPy and the BioSemi ActiveTwo system.
===== Sending an entire byte at once =====
//The following describes an issue and fix that is relevant for PsychoPy 1.83 and older. This fix will be included in version 1.84 and beyond. For a more detailed description of the issue and resolution see this PsychoPy [[https://groups.google.com/forum/#!searchin/psychopy-users/bit$20latency/psychopy-users/gN9ZSMgvTsE/uq5xePwSEwAJ
|forum thread]]//
The code used in PsychoPy to send digital codes via the LabJack device sets each bit sequentially, rather than setting the entire byte in parallel. This introduces a ~400 microsecond latency between each bit. This latency has two important consequences for use in EEG. 1) Sending a code of "255" (11111111) will have a latency relative to the stimulus onset that is ~3 milliseconds longer than sending a code of "1" (00000001). Of course, this introduces a confound when contrasting the latency of two conditions that use those codes.
To fix the problem, one needs to modify a little bit of code included in the OS X PsychoPy standalone package.
- Right click on the PsychoPy application and select ''Show Package Contents''
- Navigate to /Applications/PsychoPy2/Contents/Resources/lib/python2.7/psychopy/hardware
- Open the ''labjacks.py'' file for editing (you might want create a copy of the file before making changes)
- Replace the class U3 definition
Replace this code:
class U3(u3.U3):
def setData(self, byte, endian='big', address=6008):
"""Write 1 byte of data to the U3 port
parameters:
- byte: the value to write (must be an integer 0:255)
- endian: ['big' or 'small'] determines whether the first pin is the least significant bit or most significant bit
- address: the memory address to send the byte to
- 6008 = EIO (the DB15 connector)
"""
if endian=='big':
byteStr = '{0:08b}'.format(byte)[-1::-1]
else:
byteStr = '{0:08b}'.format(byte)
[self.writeRegister(address+pin, int(entry)) for (pin, entry) in enumerate(byteStr)]
with this code:
class U3(u3.U3):
def setData(self, byte, endian='big', address=6701):
"""Write 1 byte of data to the U3 port
parameters:
- byte: the value to write (must be an integer 0:255)
- endian: ['big' or 'small'] (ignoring) determines whether the first pin is the least significant bit or most significant bit
- address: the memory address to send the byte to
- 6700 = FIO
- 6701 (default) = EIO (the DB15 connector)
- 6702 = CIO
"""
#Upper byte is the writemask, and lower byte is the 8 lines/bits to set. Bit 0 = line 0, bit 1 = line 1, bit 2 = line 2, etc.
self.writeRegister(address, 0xFF00 + (byte&0xFF))
==== LabJack Port Addresses ====
https://labjack.com/support/datasheets/u3/hardware-description/db15
===== Setting the default LabJack address =====
**The information contained in this box is moot if you use the method above to change the port address**
PsychoPy has a built-in python library to drive the LabJack DAQ device. By default, PsychoPy uses the address for the "EI0" DB15 pins (address = 6008). We use the "FIO" terminal blocks so we need to specify the correct address (''6000''). In order to use the "FIO" terminal we need to add the following custom code component to the beginning our Builder experiment. PsychoPy users [[https://groups.google.com/forum/#!topic/psychopy-users/Fvz3lSnkAWI|thread]].
def mySetData(self, byte, endian='big', address=6000):
if endian=='big':
byteStr = '{0:08b}'.format(byte)[-1::-1]
else:
byteStr = '{0:08b}'.format(byte)
[self.writeRegister(address+pin, int(entry)) for (pin, entry) in enumerate(byteStr)]
labjacks.U3.setData = mySetData
===== Initializing the LabJack =====
==== Status attribute ====
* There seems to be a bug in Builder that results in an attribute of the p_port not being initialized (see psychopy users [[https://groups.google.com/forum/#!searchin/psychopy-users/p_port.status/psychopy-users/7aX-5nDuqbU/uehchw6LGdcJ|thread]]). Running a Builder-built experiment with LabJack digital codes will give the following error.
AttributeError:'U3' object has no attribute 'status'
This can be fixed by adding the following code to the start of the script (anywhere //after// the code that imports the LabJacks module)
p_port.status = NOT_STARTED
Alternatively, you should be able to fix this problem by using the ''custom code'' component, selecting the ''Begin Routine'' tab, and adding the following"
p_port.status = []
* The LabJacks will initialize with all bits set to hight (i.e. sending a ''255'' code). So you should also add the following code to your script (it can be added right after the code shown above).
win.callOnFlip(p_port.setData, int(1), address=6000)