Iohub pstbox sample program no longer works

The ‘pstbox.py’ sample program (psychopy/pstbox.py at release · psychopy/psychopy · GitHub), which used to work a year ago, now crashes when calling launchHubServer. Nothing has changed on my computer in the meantime except that I’ve updated PsychoPy from v1.82 to v1.85.6. The problem seems to be with its use of the serial.Pstbox class, since a similar sample program that uses the serial.Serial class instead (URL no longer active) still runs OK. To clarify, I’ve attached two simplified programs: the ‘lampsTest serial.py’ program works and the ‘lampsTest pstbox.py’ program doesn’t.

lampsTest serial.py (1.5 KB)

lampsTest pstbox.py (1.1 KB)

Has anybody else experienced this?
The error message is as follows:

Error during device creation …
<type ‘exceptions.IndexError’>
IndexError(‘boolean index did not match indexed array along dimension 0; dimension is 9 but corresponding boolean dimension is 8’,)
[’ File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\server.py”, line 591, in createNewMonitoredDevice\n device_instance_and_config=self.addDeviceToMonitor(device_class_name,deviceConfig)\n’,
’ File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\server.py”, line 781, in addDeviceToMonitor\n deviceInstance=DeviceClass(dconfig=device_config)\n’,
’ File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\devices\serial\init.py”, line 515, in init\n self._update_state()\n’,
’ File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\devices\serial\init.py”, line 528, in _update_state\n state_bits = (2**N.arange(9))[state]\n’]
Error during device creation …
<class ‘psychopy.iohub.util.exception_tools.ioHubError’>
ioHubError:
Args: (‘Error during device creation …’,)

[’ File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\server.py”, line 520, in init\n self.createNewMonitoredDevice(device_class_name,deviceConfig)\n’,
’ File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\server.py”, line 603, in createNewMonitoredDevice\n raise ioHubError(“Error during device creation …”)\n’]
<class ‘psychopy.iohub.util.exception_tools.ioHubError’>
ioHubError:
Args: (‘Error during device creation …’,)

[’ File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\launchHubProcess.py”, line 35, in run\n s = ioServer(rootScriptPathDir, ioHubConfig)\n’,
’ File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\server.py”, line 524, in init\n raise ioHubError(“Error during device creation …”)\n’]
Closing remaining open files:\uol.le.ac.uk\root\staff\home\r\rk239\My Documents\Psychopy communicating with BIOPAC\github sample programs\pstbox.hdf5…done
Traceback (most recent call last):
File “\uol.le.ac.uk\root\staff\home\r\rk239\My Documents\Psychopy communicating with BIOPAC\github sample programs\pstbox.py”, line 35, in
io = launchHubServer(**iohubkwargs)
File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\client_init_.py”, line 1504, in launchHubServer
return ioHubConnection(ioConfig)
File “C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\client_init_.py”, line 285, in init
self.iohub_status = self.startServer(ioHubConfig, ioHubConfigAbsPath)
File "C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\client_init
.py", line 943, in _startServer
isDataAvail=self.serverStdOutHasData()
File "C:\Program Files (x86)\PsychoPy2\lib\site-packages\psychopy\iohub\client_init
.py", line 1052, in _serverStdOutHasData
raise e
pywintypes.error: (109, ‘PeekNamedPipe’, ‘The pipe has been ended.’)

A bit more testing indicates that the lampsTest pstbox.py program works when run in PsychoPy v1.85.1, but not when run in PsychoPy v1.85.2.

The solution is to change line 525 in PsychoPy2\Lib\site-packages\psychopy\iohub\devices\serial_init_.py from

state_bits = (2**N.arange(9))[state]

to

state_bits = (2**N.arange(8))[state].

This line carries out something equivalent to a binary AND operation using a bit mask, where an array of values (in this case these should be 8 integers representing binary values: [1,2,4,8,16,32,64,128]), is compared item-by-item with an array of Booleans (the bit mask, in this case representing the initial state of the button box: [0,0,0,0,0,1,1,1]) and wherever the bit mask contains a ‘1’ the corresponding value in the first array is written to a new array. In this case, the new array will be [32,64,128] because only the last 3 items in the bit mask are '1’s.

The error occurs because the code in fact creates an array of 9 values ([1,2,4,8,16,32,64,128,256]) and attempts to compare this item-by-item with an array of 8 Booleans. Older versions of the Python Numpy library permitted such comparisons, I think by padding out the array of Booleans with '0’s until it was the same length as the main array. But allowing this mismatch between arrays has since been deprecated (https://github.com/numpy/numpy/pull/4353), so Numpy now throws an error. The problem is solved by changing the code to create an array of 8 values instead of 9. The 9th value (256) seems to serve no purpose in communicating with the serial port and I think it might originally have been included by mistake.

Unfortunately, not all users of PsychoPy will have administrator permission on their PC to change this line of code. In my workplace, this is the case for most users. So it would be very helpful if this correction could be included in future versions of PsychoPy as a bug fix…

Please note that the proposed fix also works when running ‘lampsTest pstbox.py’ in PsychoPy3.1.1.

However, PsychoPy3 reports an additional, unrelated error concerning iohub datastore. This error does not crash the program (the PST box lamps get switched on), but it does presumably interfere with the datastore functionality (which I don’t use). I thought I’d mention it in case anybody is interested. It seems to relate to a wider issue concerning the iohub datastore, discussed here: https://github.com/psychopy/psychopy/issues/1548. The error message is as follows.

---------------ERROR------------------
Exception AttributeError in iohub.datastore.updateDataStoreStructure:
event_cls: <class ‘psychopy.iohub.devices.serial.PstboxButtonEvent’>
event_cls_name: PSTBOX_BUTTON
event_table_label: PSTBOX_BUTTON
eventTableLabel2ClassName: PstboxButtonEvent
Error updating data store for device addition:<psychopy.iohub.devices.serial.Pstbox object at 0x10C766B0>[107]
Traceback (most recent call last):
File “C:\Program Files\PsychoPy3_PY2\lib\site-packages\psychopy\iohub\server.py”, line 657, in createNewMonitoredDevice
devt_classes)
File “C:\Program Files\PsychoPy3_PY2\lib\site-packages\psychopy\iohub\datastore_init_.py”, line 224, in updateDataStoreStructure
self.groupNodeForEvent(event_cls)))
File “C:\Program Files\PsychoPy3_PY2\lib\site-packages\psychopy\iohub\datastore_init_.py”, line 182, in groupNodeForEvent
self.emrtFile.createGroup(datevts_node, evt_group_label,
AttributeError: ‘File’ object has no attribute ‘createGroup’