Skip to content

Commit

Permalink
Merge pull request #557 from int-brain-lab/iblrigv8dev
Browse files Browse the repository at this point in the history
Iblrigv8dev
  • Loading branch information
bimac authored Nov 30, 2023
2 parents 3d16f40 + 7cce169 commit ca10fbb
Show file tree
Hide file tree
Showing 47 changed files with 855 additions and 446 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ iblrig/_version.py

.coverage*
coverage.xml

devices/camera_setup/*.layout
devices/camera_recordings/*.layout
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
---------

8.12.10
-------
* ignore user-side changes to bonsai layouts (for camera workflows only)
* error message if rig-name is not defined in Alyx
* populate delegate users
* the usual: minor fixes, clean-ups and unit-tests

8.12.9
------
* usability improvements for "Show Training Level" tool
Expand Down
67 changes: 31 additions & 36 deletions devices/F2TTL/ArCOM_F2TTL.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @File: F2TTL\ARCOM.py
# @Author: Niccolo' Bonacchi (@nbonacchi)
# @Date: Tuesday, December 7th 2021, 12:01:15 pm
Expand All @@ -26,21 +25,21 @@
import serial


class ArCOM(object):
class ArCOM:
def __init__(self, serialPortName, baudRate):
self.serialObject = 0
self.typeNames = (
"uint8",
"int8",
"char",
"uint16",
"int16",
"uint32",
"int32",
"single",
'uint8',
'int8',
'char',
'uint16',
'int16',
'uint32',
'int32',
'single',
)
self.typeBytes = (1, 1, 1, 2, 2, 4, 4)
self.typeSymbols = ("B", "b", "c", "H", "h", "L", "l")
self.typeSymbols = ('B', 'b', 'c', 'H', 'h', 'L', 'l')
self.serialObject = serial.Serial(serialPortName, timeout=10, rtscts=True)

def open(self, serialPortName, baudRate):
Expand All @@ -60,14 +59,14 @@ def write(self, *arg):
"""
nTypes = int(len(arg) / 2)
argPos = 0
messageBytes = b""
messageBytes = b''
for i in range(0, nTypes):
data = arg[argPos]
argPos += 1
datatype = arg[argPos]
argPos += 1 # not needed
if datatype not in self.typeNames:
raise ArCOMError("Error: " + datatype + " is not a data type supported by ArCOM.")
raise ArCOMError('Error: ' + datatype + ' is not a data type supported by ArCOM.')
# datatypePos = self.typeNames.index(datatype) # Not used?

if type(data).__module__ == np.__name__:
Expand All @@ -86,7 +85,7 @@ def read(self, *arg): # Read an array of values
argPos += 1
datatype = arg[argPos]
if (datatype in self.typeNames) is False:
raise ArCOMError("Error: " + datatype + " is not a data type supported by ArCOM.")
raise ArCOMError('Error: ' + datatype + ' is not a data type supported by ArCOM.')
argPos += 1
typeIndex = self.typeNames.index(datatype)
byteWidth = self.typeBytes[typeIndex]
Expand All @@ -95,11 +94,7 @@ def read(self, *arg): # Read an array of values
nBytesRead = len(messageBytes)
if nBytesRead < nBytes2Read:
raise ArCOMError(
"Error: serial port timed out. "
+ str(nBytesRead)
+ " bytes read. Expected "
+ str(nBytes2Read)
+ " byte(s)."
'Error: serial port timed out. ' + str(nBytesRead) + ' bytes read. Expected ' + str(nBytes2Read) + ' byte(s).'
)
thisOutput = np.frombuffer(messageBytes, datatype)
outputs.append(thisOutput)
Expand All @@ -116,45 +111,45 @@ class ArCOMError(Exception):
pass


if __name__ == "__main__":
if __name__ == '__main__':
import struct

port = "/dev/ttyACM3"
port = '/dev/ttyACM3'
nsamples = 6

# Hello ser
ser = serial.Serial(port, 115200, timeout=1)
ser.write(b"C")
print(int.from_bytes(ser.read(1), byteorder="little", signed=False))
ser.write(struct.pack("c", b"#"))
print(int.from_bytes(ser.read(1), byteorder="little", signed=False))
ser.write(b'C')
print(int.from_bytes(ser.read(1), byteorder='little', signed=False))
ser.write(struct.pack('c', b'#'))
print(int.from_bytes(ser.read(1), byteorder='little', signed=False))
s = 0
samples = []
while s < nsamples:
ser.write(b"V")
ser.write(b'V')
response = ser.read(4)
samples.append(int.from_bytes(response, byteorder="little", signed=False))
samples.append(int.from_bytes(response, byteorder='little', signed=False))
s += 1

print(samples)

# ser.write(struct.pack('cI', b"V", nsamples))
ser.write(b"V" + int.to_bytes(nsamples, 4, byteorder="little", signed=False))
ser.write(b'V' + int.to_bytes(nsamples, 4, byteorder='little', signed=False))
serout = ser.read(nsamples * 2)
print(serout)
print(np.frombuffer(serout, "uint16"))
print(np.frombuffer(serout, 'uint16'))
ser.close()

# Hello arc
arc = ArCOM(port, 115200)
arc.write(ord("C"), "uint8")
print(arc.read(1, "uint8"))
arc.write(ord("#"), "uint8")
print(arc.read(1, "uint8"))
arc.write(ord('C'), 'uint8')
print(arc.read(1, 'uint8'))
arc.write(ord('#'), 'uint8')
print(arc.read(1, 'uint8'))

arc.read(1, "uint8")
arc.read(1, 'uint8')
# arc.write(ord("V"), "uint8", nsamples, "uint32")
arc.write(ord("V"), "uint8")
arcout = arc.read(1, "uint16")
arc.write(ord('V'), 'uint8')
arcout = arc.read(1, 'uint16')
print(arcout)
del arc
60 changes: 30 additions & 30 deletions devices/F2TTL/Frame2TTLv2.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @File: F2TTL\Frame2TTLv2.py
# @Author: Niccolo' Bonacchi (@nbonacchi)
# @Date: Tuesday, December 7th 2021, 12:01:50 pm
from ArCOM_F2TTL import ArCOM
import numpy as np
import time

import numpy as np
from ArCOM_F2TTL import ArCOM


class Frame2TTLv2(object):
class Frame2TTLv2:
def __init__(self, PortName):
self.Port = ArCOM(PortName, 115200)
self.Port.write(ord("C"), "uint8")
handshakeByte = self.Port.read(1, "uint8")
self.Port.write(ord('C'), 'uint8')
handshakeByte = self.Port.read(1, 'uint8')
if handshakeByte != 218:
raise F2TTLError("Error: Frame2TTL not detected on port " + PortName + ".")
self.Port.write(ord("#"), "uint8")
hardwareVersion = self.Port.read(1, "uint8")
raise F2TTLError('Error: Frame2TTL not detected on port ' + PortName + '.')
self.Port.write(ord('#'), 'uint8')
hardwareVersion = self.Port.read(1, 'uint8')
if hardwareVersion != 2:
raise F2TTLError("Error: Frame2TTLv2 requires hardware version 2.")
raise F2TTLError('Error: Frame2TTLv2 requires hardware version 2.')
self._lightThreshold = 150
# This is not a threshold of raw sensor data.
self._darkThreshold = -150
Expand All @@ -31,7 +31,7 @@ def lightThreshold(self):

@lightThreshold.setter
def lightThreshold(self, value):
self.Port.write(ord("T"), "uint8", (value, self.darkThreshold), "int16")
self.Port.write(ord('T'), 'uint8', (value, self.darkThreshold), 'int16')
self._lightThreshold = value

@property
Expand All @@ -40,24 +40,24 @@ def darkThreshold(self):

@darkThreshold.setter
def darkThreshold(self, value):
self.Port.write(ord("T"), "uint8", (self.lightThreshold, value), "int16")
self.Port.write(ord('T'), 'uint8', (self.lightThreshold, value), 'int16')
self._darkThreshold = value

def setLightThreshold_Auto(self): # Run with the sync patch set to black
self.Port.write(ord("L"), "uint8")
self.Port.write(ord('L'), 'uint8')
time.sleep(3)
newThreshold = self.Port.read(1, "int16")
newThreshold = self.Port.read(1, 'int16')
self.lightThreshold = newThreshold[0]

def setDarkThreshold_Auto(self): # Run with the sync patch set to white
self.Port.write(ord("D"), "uint8")
self.Port.write(ord('D'), 'uint8')
time.sleep(3)
newThreshold = self.Port.read(1, "int16")
newThreshold = self.Port.read(1, 'int16')
self.darkThreshold = newThreshold[0]

def read_sensor(self, nSamples): # Return contiguous samples (raw sensor data)
self.Port.write(ord("V"), "uint8", nSamples, "uint32")
value = self.Port.read(nSamples, "uint16")
self.Port.write(ord('V'), 'uint8', nSamples, 'uint32')
value = self.Port.read(nSamples, 'uint16')
return value

def measure_photons(self, num_samples: int = 250) -> dict:
Expand All @@ -66,12 +66,12 @@ def measure_photons(self, num_samples: int = 250) -> dict:
"""
sensorData = self.read_sensor(num_samples)
out = {
"mean_value": float(sensorData.mean()),
"max_value": float(sensorData.max()),
"min_value": float(sensorData.min()),
"std_value": float(sensorData.std()),
"sem_value": float(sensorData.std() / np.sqrt(num_samples)),
"nsamples": float(num_samples),
'mean_value': float(sensorData.mean()),
'max_value': float(sensorData.max()),
'min_value': float(sensorData.min()),
'std_value': float(sensorData.std()),
'sem_value': float(sensorData.std() / np.sqrt(num_samples)),
'nsamples': float(num_samples),
}
return out

Expand All @@ -80,10 +80,10 @@ def __repr__(self):
with no properties or methods specified
"""
return (
"\nBpodHiFi with user properties:" + "\n\n"
"Port: ArCOMObject(" + self.Port.serialObject.port + ")" + "\n"
"lightThreshold: " + str(self.lightThreshold) + "\n"
"darkThreshold: " + str(self.darkThreshold) + "\n"
'\nBpodHiFi with user properties:' + '\n\n'
'Port: ArCOMObject(' + self.Port.serialObject.port + ')' + '\n'
'lightThreshold: ' + str(self.lightThreshold) + '\n'
'darkThreshold: ' + str(self.darkThreshold) + '\n'
)

def __del__(self):
Expand All @@ -94,11 +94,11 @@ class F2TTLError(Exception):
pass


if __name__ == "__main__":
if __name__ == '__main__':
# Example usage:
# port = 'COM4'
# port = '/dev/ttyACM0'
port = "/dev/serial/by-id/usb-Teensyduino_USB_Serial_10295450-if00"
port = '/dev/serial/by-id/usb-Teensyduino_USB_Serial_10295450-if00'
f = Frame2TTLv2(port)
print(f)

Expand Down
2 changes: 1 addition & 1 deletion devices/F2TTL/Frame2TTLv2_Demo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from Frame2TTLv2 import Frame2TTLv2

F = Frame2TTLv2("/dev/ttyACM3")
F = Frame2TTLv2('/dev/ttyACM3')
F.lightThreshold = 150 # See note about threshold units in Frame2TTLv2.py
F.darkThreshold = -150
myRawData = F.read_sensor(6) # Read 20k samples of raw, contiguous sensor data
Expand Down
Loading

0 comments on commit ca10fbb

Please sign in to comment.