Skip to main content
Skip table of contents

Examples

Establishing a connection to VPixx hardware 

Must be called at the beginning of every experiment

CODE
#Code block best positioned "Before Experiment" so any problems are caught right away
#import our library and open the device connection
#throw an error if device is not connected properly
from pypixxlib import _libdpx as dp
dp.DPxOpen()
isReady = dp.DPxIsReady()
if not isReady:
    raise ConnectionError('VPixx Hardware not detected! Check your connection and try again.')

Enabling Pixel Mode and creating a Pixel Trigger

Pixel Mode is a method of sending automated TTL triggers locked to visual stimulus onset. Read more about this mode here: Sending Triggers with Pixel Mode .

This block enables Pixel Mode on our data acquisition systems (note: it is on by default for the VIEWPixx /EEG). It also creates a helper command called “DrawPixelModeTrigger” which you can then call just before the frame where you would like the trigger to fire. The last few lines can be pasted in their own block just before the target video frame; these will generate your custom trigger. 

PY
#Code block best positioned "Before Experiment" or "Begin Experiment"
#Assumes library has been imported and device is connected
#Configure hardware to be in Pixel Mode
dp.DPxEnablePixelMode()
dp.DPxWriteRegCache()
#Helper function to draw pixel trigger
def drawPixelModeTrigger(win, pixelValue):
    #takes a pixel colour and draws it as a single pixel in the top left corner of the window
    #window must cover top left of screen to work
    #interpolate must be set to FALSE before color is set
    #call this just before flip to ensure pixel is drawn over other stimuli
    topLeftCorner = [-win.size[0]/2, win.size[1]/2]
    line = visual.Line(
            win=win,
            units = 'pix',
            start=topLeftCorner,
            end=[topLeftCorner[0]+1, topLeftCorner[1]],
            interpolate = False,
            colorSpace = 'rgb255',
            lineColor = pixelValue)
    line.draw()
#Uncomment and paste the following in a code block just before your target video frame to draw your pixel trigger.
#There should be no delay between this code and your target video frame, so if you are drawing other stimuli make 
#sure to draw them right away. You may want to start a routine where stimuli onset occurs at t0 and add this code 
#block in the "Begin Routine" phase
#myTriggerValue = 33
#myPixelValue = dp.DPxTrigger2RGB(myTriggerValue)
#drawPixelModeTrigger(win, myPixelValue)

Loading an audio waveform into device memory

Save your audio file to VPixx hardware memory for playback during the experiment. 

PY
#Code block best positioned "Begin Experiment"
#Assumes libdpx has been imported and device is connected
#Requires scipy for importing audio files
from scipy.io import wavfile
#file path to sound file
soundFile = 'C:/.../myfile.wav'
#import sound file into Python
fs, audio_data = wavfile.read(soundFile)
maxScheduleFrames = len(audio_data) 
#some settings
volume = 0.5 #50 percent
bufferAddress = int(16e6) 
onsetDelay = 0.0 
stereoMode = 'mono'
dp.DPxInitAudCodec()
dp.DPxWriteAudioBuffer(audio_data, bufferAddress)
dp.DPxSetAudioSchedule(onsetDelay, fs, maxScheduleFrames, stereoMode, bufferAddress)    
dp.DPxWriteRegCache()

Setting up Button Schedules

This mode allows you to define unique TTL waveforms for each of your RESPONSEPixx buttons and save them on the hardware. Button presses will then immediately trigger playback of these waveforms on the acquisition system’s digital output. Use this method to pass button activity to other hardware (MEG, EEG).

PY
#Code block best positioned "Beginning of Experiment" when parameters are being set
#The schedule will work automatically, including catching any accidental presses
#Assumes library has been imported and device is connected

#Enable debounce. When a DIN transitions, ignore further DIN transitions for next 30 milliseconds 
#(good for response buttons and other mechanical inputs)
dp.DPxEnableDinDebounce()

#Set our mode. The mode can be:
#  0 -- The schedules starts on a raising edge (press of RPx /MRI, release of RPx)
#  1 -- The schedules starts on a falling edge (release of RPx /MRI, press of RPx)
#  2 -- The schedules starts on a raising and on a falling edge (presses and releases, both RPx types)
# For mode 0 and 1, you put the schedule at baseAddr + 4096*DinValue
# For mode 2, you put the schedule of a falling edge at baseAddr + 4096*DinValue + 2048*DinValue 
# and a rising edge at baseAddr + 4096*DinValue + 2048
#Not sure what DinValues correspond to which buttons? Have special wiring? 
#Check directly by using out PyPixx > Digital I/O demo and pressing buttons

dp.DPxSetDoutButtonSchedulesMode(0)
signalLength = 6
baseAddress = int(9e6)

#Red button (DinValue 0)
redSignal = [1, 0, 0, 0, 0, 0] #single pulse on dout 0
redAddress =  baseAddress + 4096*0
dp.DPxWriteDoutBuffer(redSignal, redAddress)

#Yellow button (DinValue 1)
yellowSignal = [1, 0, 1, 0, 0, 0] #two pulses on dout 0
yellowAddress =  baseAddress + 4096*1
dp.DPxWriteDoutBuffer(yellowSignal, yellowAddress)

#Green button (DinValue 2)
greenSignal = [2, 0, 0, 0, 0, 0] #single pulse on dout 1
greenAddress =  baseAddress + 4096*2
dp.DPxWriteDoutBuffer(greenSignal, greenAddress)

#Blue button (DinValue 3)
blueSignal = [2, 0, 2, 0, 0, 0] #two pulses on dout 1
blueAddress =  baseAddress + 4096*3
dp.DPxWriteDoutBuffer(blueSignal, blueAddress)

scheduleOnset = 0.0 #no delay
scheduleRate = 2 #waveform playback rate 2 samples/sec

dp.DPxSetDoutSchedule(scheduleOnset, scheduleRate, signalLength+1, baseAddress)
dp.DPxEnableDoutButtonSchedules()
dp.DPxWriteRegCache()

Setting up and starting a RESPONSEPixx listener

RESPONSEPixx button box activity is recorded on the digital input of the data acquisition system. We use a special schedule called a digital input log to record only changes in the state of this port, signaling either a button press or a release.

A RESPONSEPixx Listener is a special class developed for our OOP library that encapsulates all of the commands required to set up and collect button activity from the digital input log. While it is not necessary to use a Listener to monitor button activity, this tool streamlines button box monitoring.  The RPxButtonListener begins recording data as soon as it is created. It can listen for button presses, button releases, or both. 

PY
#Code block best positioned "Beginning of Routine" at either start of a block or a trial
#depending on how continuously you want to record data
#Assumes library has been imported and device is connected
from pypixxlib import responsepixx as rp

#Create button listener, and pass button box type as argument. 
# Accepted values (not case sensitive):
#     1) 'handheld'
#     2) 'handheld - mri'
#     3) 'dual - mri'
#     4) 'dual handheld'
#     5) 'mri 10 button'

#Using a custom button box and need a hand? Contact our tech support team (support@vpixx.com)
listener = rp.ButtonListener("dual - mri") 

Checking for a RESPONSEPixx button press

Once you have a ButtonListener running (see previous example), you can check for new button activity strategically during your experiment. Below is an example of log checking using an instance of the RPxButtonListener class.

Timestamps reported are VPixx hardware clock. If you want to compare the button event timing to some other event, like visual stimulus onset, you can take frame-accurate timestamps using the code in example 8. Do not equate PsychoPy system time and VPixx hardware time. Separate clock systems can drift and desynchronize over time, making timing comparisons inaccurate.

PY
#Code block best positioned "End of Routine" where routine is a trial 
#Reports all new button activity since the listener was instantiated OR the last call to updateLogs()
#Requires VPixx hardware to be connected, and an RPxButtonListener must be instantiated 
import numpy as np

#This follows the example above, using an dual - mri button box. 
#Logged button events take the format [timetag, buttonID, eventType]
    # timetag is the time in seconds since your VPixx hardware last booted up
    # buttonID is the button that was active. Below is a list of button IDs to help interpret code:  
        # "handheld" button IDs: {0:'red',1:'yellow',2:'green',3:'blue',4:'white'}
        # "handheld - mri" button IDs: {0:'red',1:'yellow',2:'green',3:'blue'}
        # "dual - mri" button IDs: {0:'red',1:'yellow',2:'green',3:'blue'}
        # "dual handheld" button IDs: {0:'red',1:'yellow',2:'green',3:'blue'}
        # "mri 10 button" button IDs: {0:'red left',1:'yellow left',2:'green left',3:'blue left',
        #                               4:'white left',5:'red right',6:'yellow right',7:'green right',
        #                               8:'blue right',9:'white right'}
    # eventType can be either "Push" or "Release"
#If more than one event is logged, they will all be reported in the output.

#Only listen for red or yellow pushes. You can alter these variables to listen for different events
buttonSubset = [0,1] 
recordPushes = True
recordReleases = False

# update the Din logs for any new activity
listener.updateLogs() 
output = listener.getNewButtonActivity(buttonSubset, recordPushes, recordReleases)

#This bit of code saves the logged events to a .csv file in the working directory. 
#If you call it repeatedly, it will append any new data to the same file.
#You may want to change the file name between blocks or participants to keep data organized.     
myFileName = 'RPxData.csv'
with open(myFileName, 'a') as RPxData:
    #save output
    if np.size(output)>0:
            np.savetxt(RPxData, output, delimiter=",", fmt='%s', comments="")

Closing the connection to hardware

A simple cleanup code block to run at the end of your experiment.

PY
#Code block best positioned "After Experiment"   
#Assumes library has been imported and device is connected
dp.DPxStopAllScheds()
dp.DPxWriteRegCache() 
dp.DPxClose() 
JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.