Basic Demos

Our examples will showcase how easy it is to use a VPixx device with our package.

Tip

We will be using an object-oriented approach to use VPixx devices. If you are more comfortable programming using a more imperative/functional way but you still want to use Python, you can use the Libdpx Wrapper module, which is a simple wrapper for our ANSI C SDK.

Example 1 - Setting up a device in High-bit depth grey-scale mode.

You must first consider which device you have. In this example we will use a VIEWPixx3D.

1from pypixxlib.viewpixx import VIEWPixx3D
2# viewpixx and VIEWPixx3D would need to be replaced by the appropriate devices.
3my_device = VIEWPixx3D() # Opens and initiates the device
4my_device.setVideoMode('M16') # Set the right video mode
5my_device.updateRegisterCache() # Update the device

Example 2 - Setting up a PROPixx to display in 480 Hz.

This example is only meant for the PROPixx as it is the only device able to display stimuli at 480 Hz. To do so, we limit our resolution to 1/4 of the screen to display 4 times faster. Indeed, your stimulus needs to be created as follow:

Quadrant 1

Quadrant 2

Quadrant 3

Quadrant 4

One frame at 120 Hz will represent 4 frames at 480 Hz on the PROPixx, and each of those 4 frames must be put in order in the quadrants 1, 2, 3 and 4.

1from pypixxlib.propixx import PROPixx
2my_device = PROPixx()
3my_device.setDlpSequencerProgram('QUAD4X')
4my_device.updateRegisterCache()
5# You can now send you stimulus at 120 Hz to be displayed at 480 Hz!

Example 3 - Setting up a PROPixx to display in 1440 Hz.

1440 Hz is very similar to 480 Hz in the set-up process. To get 1440 Hz, we use the fact that every quadrants defined above has three channels of information (RGB). Quadrant 1’s red information will define the first frame we display at 1440 Hz, Quadrant 2’s red will be the 2nd, and after red we use green information, then blue. In other words: Q1R, Q2R, Q3R, Q4R, Q1G, Q2G, Q3G, Q4G, Q1B, Q2B, Q3B, Q4B. This allows us to have 12 high speed frames every normal speed frame, giving 1440 Hz.

1from pypixxlib.propixx import PROPixx
2my_device = PROPixx()
3my_device.setDlpSequencerProgram('QUAD12X')
4my_device.updateRegisterCache()
5# You can now send you stimulus at 120 Hz to be displayed at 1440 Hz!

Example 4 - Setting up a PROPixx for a 3D experiment.

In this example, we will set up the PROPixx for rear projection, ceiling mode and use of a polariser. We will also set the PROPixx so that it keeps this configuration after a power down. We will also have the PROPixx Controller send out audio stimuli.

There exists four ways to set up the polariser, depending on what you wish to achieve.

  1. If the video source is set to SWTP3D: my_device.setVideoSource('SWTP3D')

  2. If you are using Blue Lines to sync your 3D stimulus: my_device.setVideoBlueLine(True)

  3. If you are using the red and blue 3D sequencer mode: my_device.setDlpSequencerProgram('RB3D')

  4. You can manually activate the polariser,(this is called VESA Free Run mode): my_device.setVesaFreeRun(True)

 1from pypixxlib.propixx import PROPixx, PROPixxCTRL
 2from pypixxlib._libdpx import DPxSelectDevice
 3my_device = PROPixx()
 4my_device_controller = PROPixxCTRL()
 5
 6
 7my_device.setRearProjectionMode(True)# Sets the projector to read-projection mode.
 8my_device.setCeilingMountMode(True) # Sets the projector to ceiling-mount mode.
 9my_device.setVesaFreeRun(True)  # Sets the VESA port to work with the polariser.
10my_device.updateRegisterCache() # Update the new modes to the device.
11my_device.setCustomStartupConfig() # The projector will remember this configuration.
12# The audio is done on the controller, so the next functions use the controller object.
13my_device_controller.audio.initializeCodec() # Configures initial CODEC state.
14my_device_controller.audio.setLeftRightMode('mono') # Set which mode the audio will be output.
15my_device_controller.audio.setAudioBuffer(0, 64) # Set the audio to start at address 0, and size 64.
16
17
18# Now we must create the audio stimulus.
19# This is done by simply filling a list with a sound wave.
20audio_stim = []
21import math
22for i in range(32):
23    audio_stim.append(int(32767 * math.sin(2.0 * math.pi * i / 32.0)))
24my_device_controller.writeRam(0, audio_stim) # Write the audio stimulus in the ram.
25my_device_controller.audio.setVolume(0.25)
26my_device_controller.updateRegisterCache() # Send everything to the device.
27
28# We must at this point create the audio schedule
29# The first parameter is the schedule onset, which we set to 0,
30# meaning that the first schedule tick will occur immediately once the schedule starts.
31# The second and third parameters indicate that the audio samples will be played at 40 kHz.
32# The forth parameter is a schedule counter, indicating the number of ticks
33# that the schedule should run before stopping.
34# We'll run it for 16000 samples, which will take 16000/40000 = 400 ms.
35
36my_device_controller.audio.setAudioSchedule(0, 40000, 'hz', 16000)
37my_device_controller.audio.startScheduleLeft()
38my_device_controller.updateRegisterCache()
39# Close the devices
40my_device.close()
41my_device_controller.close()

Example 5 - Changing the back-light intensity on a VIEWPixx

Our VIEWPixx offer a customizable back-light level, should you wish to work with specific luminance values.

1from pypixxlib.viewpixx import VIEWPixxEEG
2my_device = VIEWPixxEEG() # Create an instance of your device.
3my_device.setBacklightIntensity(35) # Value between 0-255 for the intensity.
4my_device.updateRegisterCache() # Send the value to the device.
5my_device.getBacklightIntensity() # Double check our value was sent and applied
635

Example 6 - Recording changes in digital-in

If you are running an experiment that sends triggers over a DB-25 cable, it is possible to record those changes with a DATAPixx.

 1from pypixxlib.datapixx import DATAPixx
 2my_device = DATAPixx()
 3din_state = my_device.din.getValue()
 4# Start your experiment
 5experiement_is_running = True
 6while experiement_is_running:
 7    old_state = din_state
 8    my_device.updateRegisterCache()
 9    din_state = my_device.din.getValue()
10    if old_state is not din_state: # Something triggered.
11        # Now we want to check, for example, if pin 6 triggered.
12        if (old_state & 2**6) is not (din_state & 2**6):
13            print 'Pin 6 triggered!'
14            experiement_is_running = False
15        else:
16            print 'Pin 6 is in the same state as before'
17# Finish your experiment

Example 7 - How to verify the chromacity and luminance of the colors of your device using i1Device

Most of our devices come calibrated as D65, but if you want to verify the calibration or get a specific value for a colour/brightness, you can use the i1Display and i1Pro modules.

 1from pypixxlib.i1 import I1Display # We will use an i1Display here
 2
 3
 4# Initialize the device.
 5my_device = I1Display()
 6my_device.setCurrentCalibration('RGB LED') # We will be using a device with RGB LEDs
 7print 'Current calibration is: ', my_device.getCurrentCalibration() # Verify we have the right calibration
 8
 9# Set the color/intensity you wish to measure
10my_device.runMeasurement()
11print 'next acquisition' # Change to the next color/intensity
12my_device.runMeasurement()
13print 'next acquisition' # Change to the next color/intensity
14my_device.runMeasurement()
15
16results = my_device.getAllMeasurement() # Get a list of all measurements
17for i in range(len(results)):
18    print results[i] # Print the different measurements
19
20my_device.printLatestMeasurement() # If you want to print your latest measurement
21
22my_device.close()  # Close the device.

Example 8 - How to read button presses from a RESPONSEPixx

Pypixxlib supports two ways of interacting with VPixx hardware. First, you can create device objects and call their functions in an object-oriented style, as the previous demos have shown. You can also use the libdpx wrapper to program sequentially as you would in other programs like MATLAB. Example 8 shows how the two methods can be used to read and report button presses using the RESPONSEPixx and the digital input log.

First, here is the object-oriented approach:

 1from pypixxlib.datapixx import DATAPixx3
 2from psychopy import core
 3
 4#connect to VPixx device
 5device = DATAPixx3()
 6
 7#First, let's make a dictionary of codes that correspond to our buttons. This is in decimal.
 8#Note 1: these codes ARE NOT UNIVERSAL. You can check what your own button codes are using the PyPixx Digital I/O demo
 9#Note 2: these codes are for single button presses only. If two buttons are pressed at the same time this will generate a unique code, which we will ignore
10buttonCodes = {65527:'blue', 65533:'yellow', 65534:'red', 65531:'green', 65519:'white', 65535:'button release'}
11exitButton = 'white'
12
13myLog = device.din.setDinLog(12e6, 1000)
14device.din.startDinLog()
15device.updateRegisterCache()
16startTime = device.getTime()
17finished = False
18
19
20#let's create a loop which checks the schedule at 0.25 s intervals for button presses.
21#Any time a button press is found, we print the timestamp and button pressed.
22#If a designated exit button is pressed, we disconnect.
23while finished == False:
24    #read device status
25    device.updateRegisterCache()
26    device.din.getDinLogStatus(myLog)
27    newEvents = myLog["newLogFrames"]
28
29    if newEvents > 0:
30        eventList = device.din.readDinLog(myLog, newEvents)
31
32        for x in eventList:
33           if x[1] in buttonCodes:
34                #look up the name of the button
35                buttonID = buttonCodes[x[1]]
36
37                #get the time of the press, since we started logging
38                time = round(x[0] - startTime, 2)
39                printStr = 'Button pressed! Button code: ' + str(x[1]) + ', Button ID: ' + buttonID + ', Time:' + str(time)
40                print(printStr)
41                if buttonID == exitButton:
42                    finished = True
43    core.wait(0.25)
44
45#Stop logging
46device.din.stopDinLog()
47device.updateRegisterCache()

And second, the libdpx version:

 1from pypixxlib._libdpx import DPxOpen, DPxClose, DPxWriteRegCache, DPxUpdateRegCache, DPxGetTime, DPxStopDinLog
 2from pypixxlib._libdpx import DPxSetDinLog, DPxStartDinLog, DPxGetDinStatus, DPxReadDinLog, DPxEnableDinDebounce
 3from psychopy import core
 4
 5#Connect to VPixx device
 6DPxOpen()
 7
 8#First, let's make a dictionary of codes that correspond to our buttons. This is in decimal (base 10).
 9#Note 1: these codes ARE NOT UNIVERSAL. You can check your own button codes by modifying this script to print all event codes, and testing each button
10#Note 2: these codes are for single button presses only. If two buttons are pressed at the same time this will generate a unique code, which we will ignore
11buttonCodes = {65527:'blue', 65533:'yellow', 65534:'red', 65531:'green', 65519:'white', 65535:'button release'}
12
13#Let's enable a digital input log on our device, at buffer address 12e6, with size 1000
14#This log ONLY marks rising and falling voltages on the digital input, and when they occur.
15#This means it will give us both button press and button release times.
16logStatus = DPxSetDinLog(0,1000)
17
18#Let's also enable debounce to avoid noise
19DPxEnableDinDebounce()
20
21#This is our start command, but it won't take effect until it is passed to the device register
22DPxStartDinLog()
23
24#Let's push these commands to the device register, and record the time this occurred
25DPxUpdateRegCache()
26startTime = DPxGetTime()
27
28#Let's create a loop which checks the log for button presses every 0.25 seconds.
29#Any time a button press or release is logged, we print the timestamp and details.
30#If our designated exit button is pressed, we stop logging.
31exitButton = 'white'
32finished = False;
33
34while finished == False:
35    #read device status
36    DPxUpdateRegCache()
37
38    #check log status and see if there are new log frames since previous read
39    DPxGetDinStatus(logStatus)
40    newData = logStatus['newLogFrames']
41
42    #if new log entries
43    if newData > 0:
44
45        #read all new events in log. The log is an m x 2 array of timetags and event codes
46        log = DPxReadDinLog(logStatus, int(newData))
47
48        #check new events to see if they are our button presses/release
49        for x in log:
50           if x[1] in buttonCodes:
51
52               #look up the name of the button
53                buttonID = buttonCodes.get(x[1])
54
55                #get the time of the press, since we started logging
56                time = round(x[0] - startTime, 2)
57
58                #print a message to the display
59                printStr = 'Button pressed! Button code: ' + str(x[1]) + ', Button ID: ' + buttonID + ', Time:' + str(time)
60                print(printStr)
61
62                #check if we should stop logging
63                if buttonID == exitButton:
64                    finished = True
65
66    #wait 0.25 seconds before next read of log
67    core.wait(0.25)
68
69DPxStopDinLog()
70
71#disconnect from device
72print('All done! Shutting down')
73DPxClose()

These basic demos should help you use your VPixx device. All possible functions are documented, and every module defines what it has access to. If you have any question or run into any problems, please do not hesitate to contact us.