Skip to main content
Skip table of contents

Combining Pixel Mode GB and buttonSchedules

This demo creates buttonschedules for four buttons and enables Pixel Mode GB. A stimulus is presented with a pixel drawn in the top lefthand corner to generate a digital output trigger. Button presses are logged and saved to .csv. The stimulus and trigger update on button press.

PY


#Beginning of experiment - initialize
from psychopy import visual
from pypixxlib import _libdpx as dp
import pandas as pd


def enableButtonSchedules():
    #Create our digital output waveforms. Each button press (rising edge) triggers a 
    #1 msec trig on the corresponding dout pin, followed by 2 msec on low. 
    #We'll use the dual /MRI as our example. DinChannels will depend on your button box type, you can use the PyPixx Digital I/O demo to verify your channel mappings.
    #Note that if PixelModeGB is enabled it will control dout 8-23, dout waveforms which try to alter these will have no effect

    #Din0 - Red
    redWaveform = [1, 0, 0]

    #Din1 - Yellow
    yellowWaveform = [2, 0, 0]

    #Din2 - Green
    greenWaveform = [4, 0, 0]

    #Din3 - Blue
    blueWaveform = [8, 0, 0]

    #Let's write the waveforms into the DPx memory. The address is set by 0 + 4096*channel_of_desired_digital_in_trigger
    redAdd = 0+4096*0
    yellowAdd = 0+4096*1
    greenAdd = 0+4096*2
    blueAdd = 0+4096*3

    #write schedules into ram
    dp.DPxWriteRam(redAdd, redWaveform)
    dp.DPxWriteRam(yellowAdd, yellowWaveform)
    dp.DPxWriteRam(greenAdd, greenWaveform)
    dp.DPxWriteRam(blueAdd, blueWaveform)

    #configure buffer-- only need to configure the first one, rest will follow the same format
    dp.DPxSetDoutBuff(redAdd, len(redWaveform)*2)
    dp.DPxSetDoutSched(0, 10, 'hz', len(redWaveform)+1)
    dp.DPxUpdateRegCache()

    #turn off debounce so button jitter is suppressed
    dp.DPxEnableDinDebounce()

    #Enable button schedules, set mode to 1 for RPx /MRI setup
    dp.DPxEnableDoutButtonSchedules()
    dp.DPxSetDoutButtonSchedulesMode(1)
    dp.DPxWriteRegCache()

def Trigger2RGB(trigger):
    #helper function determines pixel mode RGB 255 colour value based on 24-bit trigger (in decimal, base 10)
    #returns a list with R, G and B elements
    
    # return [red, green, blue]
    return [ trigger%256, (trigger>>8)%256, (trigger>>16)%256]

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()


#-----------------------------------------------------------------------------
#SCRIPT START
#Open
dp.DPxOpen()

#Initialize pixelModeGB
dp.DPxEnableDoutPixelModeGB()

#enableButtonSchedules
enableButtonSchedules()

#enable DinLog for retrieving copy of button presses
myDict = dp.DPxSetDinLog()
dp.DPxStartDinLog()
dp.DPxUpdateRegCache()
column_headers = ['TimeTag','DigitalInput']

#create a list of arbitrary trig vals-- dout 8 and 9 here
trigList = [2**9,2**8,2**9]

#stimulus colors
colors = ['red', 'green', 'blue']

##STIMULUS PRESENTATION
# Create a window
win = visual.Window(screen=1, fullscr=True, color='black', units='pix')

for i in range(0,3):
    # Create a stimulus (e.g., a square)
    stimulus = visual.Rect(win, width=100, height=100, fillColor=colors[i], pos=(0, 0))
    stimulus.draw()
    
    #draw trigger pixel
    triggerPixelVal = Trigger2RGB(trigList[i])
    drawPixelModeTrigger(win, triggerPixelVal)
    win.flip()
    
    # Wait for a button press to continue
    while True:
        dp.DPxUpdateRegCache()
        dp.DPxGetDinStatus(myDict)
        
        #listen for 2 events: button press/release
        if myDict['newLogFrames'] > 1:
            data = dp.DPxReadDinLog(myDict, myDict['newLogFrames'])
            
            # Create a DataFrame using pandas
            trial_frame = pd.DataFrame(data, columns=column_headers)
            if (i==0):
                exp_data=trial_frame
            else:
                exp_data = pd.concat([exp_data, trial_frame])
            break

# Save the DataFrame to a CSV file
csv_filename = 'sample_data.csv'
exp_data.to_csv(csv_filename, index=False)

#Shut down
dp.DPxStopAllScheds()
dp.DPxDisableDoutPixelModeGB()
dp.DPxWriteRegCache()
dp.DPxClose()
win.close()        
JavaScript errors detected

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

If this problem persists, please contact our support.